Build a CMS in an Afternoon with PHP and MySQL

  You are currently not logged in. You can view the forums, but cannot post messages. Log In | Register

21-Jan-11 00:00
This is a forum topic for discussing the article "Build a CMS in an Afternoon with PHP and MySQL":

http://www.elated.com/articles/cms-in-an-afternoon-php-mysql/

Learn how to build a complete content management system using PHP and MySQL in just a few hours. Full code download included.
07-Feb-11 13:02
I'm developing on a localhost and am getting some errors after attaching the cms to to a html site to use it as a newsletter.

These are the errors I'm getting:

Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at C:\xampp\htdocs\....\.....\config.php:14) in C:\xampp\htdocs\......\.....\admin.php on line 4

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\.....\.....\config.php:14) in C:\xampp\htdocs\.....\.....\admin.php on line 44

What would you suggest checking to troubleshooting this? Thanks, Jason
07-Feb-11 17:30
Hi Jason,

Make sure you have nothing before your opening '<?php' tag in your config.php file (not even whitespace). Similarly, make sure there's nothing after your closing '?>' tag.

Cheers,
Matt

--
Matt Doyle, Elated
07-Feb-11 17:51
Thanks for the reply. I removed a space below the ending php tags in the config file, but it is still throwing the same error.
07-Feb-11 18:08
Are you sure it's exactly the same error?

You shouldn't be getting the same error if you've removed all characters after the ?>.

Matt

--
Matt Doyle, Elated
07-Feb-11 18:20
When I click on site admin this is the error displayed: Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at C:\xampp\htdocs\lumber\cms\config.php:13) in C:\xampp\htdocs\lumber\cms\admin.php on line 3

but the login form still displays. When I log in these are the errors that display: Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at C:\xampp\htdocs\lumber\cms\config.php:13) in C:\xampp\htdocs\lumber\cms\admin.php on line 3

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\lumber\cms\config.php:13) in C:\xampp\htdocs\lumber\cms\admin.php on line 43

Nothing else shows up except for the errors.
07-Feb-11 18:26
So it's now line 13, not 14.

Your config.php must be outputting something (either that or PHP is lying!). The only thing I can think of is that you have whitespace outside your <?php ... ?> tags.

If you post your config.php here then I can take a look.

--
Matt Doyle, Elated
07-Feb-11 18:42

<?php
ini_set( "display_errors", true );
date_default_timezone_set( "America/Indiana/Indianapolis" ); // http://www.php.net/manual/en/timezones.php
define( "DB_DSN", "mysql:host=localhost;dbname=cms" );
define( "DB_USERNAME", "...." );
define( "DB_PASSWORD", "....." );
define( "CLASS_PATH", "classes" );
define( "TEMPLATE_PATH", "templates" );
define( "HOMEPAGE_NUM_ARTICLES", 5 );
define( "ADMIN_USERNAME", "admin" );
define( "ADMIN_PASSWORD", "pass" );
require( CLASS_PATH . "/Article.php" );
?>


These are the 13 lines in my config file (took out the user and password).
07-Feb-11 18:55
Hi Jason,

Check there's no whitespace at the start or end of your Article.php file either.

Matt

--
Matt Doyle, Elated
07-Feb-11 19:04

<?php

/**
* Class to handle articles
*/

class Article
{
// Properties

/**
* @var int The article ID from the database
*/
public $id = null;

/**
* @var int When the article is to be / was first published
*/
public $publicationDate = null;

/**
* @var string Full title of the article
*/
public $title = null;

/**
* @var string A short summary of the article
*/
public $summary = null;

/**
* @var string The HTML content of the article
*/
public $content = null;


/**
* Sets the object's properties using the values in the supplied array
*
* @param assoc The property values
*/

public function __construct( $data=array() ) {
if ( isset( $data['id'] ) ) $this->id = (int) $data['id'];
if ( isset( $data['publicationDate'] ) ) $this->publicationDate = (int) $data['publicationDate'];
if ( isset( $data['title'] ) ) $this->title = preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['title'] );
if ( isset( $data['summary'] ) ) $this->summary = preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['summary'] );
if ( isset( $data['content'] ) ) $this->content = $data['content'];
}


/**
* Sets the object's properties using the edit form post values in the supplied array
*
* @param assoc The form post values
*/

public function storeFormValues ( $params ) {

// Store all the parameters
$this->__construct( $params );

// Parse and store the publication date
if ( isset($params['publicationDate']) ) {
$publicationDate = explode ( '-', $params['publicationDate'] );

if ( count($publicationDate) == 3 ) {
list ( $y, $m, $d ) = $publicationDate;
$this->publicationDate = mktime ( 0, 0, 0, $m, $d, $y );
}
}
}


/**
* Returns an Article object matching the given article ID
*
* @param int The article ID
* @return Article|false The article object, or false if the record was not found or there was a problem
*/

public static function getById( $id ) {
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "SELECT *, UNIX_TIMESTAMP(publicationDate) AS publicationDate FROM articles WHERE id = :id";
$st = $conn->prepare( $sql );
$st->bindValue( ":id", $id, PDO::PARAM_INT );
$st->execute();
$row = $st->fetch();
$conn = null;
if ( $row ) return new Article( $row );
}


/**
* Returns all (or a range of) Article objects in the DB
*
* @param int Optional The number of rows to return (default=all)
* @param string Optional column by which to order the articles (default="publicationDate DESC")
* @return Array|false A two-element array : results => array, a list of Article objects; totalRows => Total number of articles
*/

public static function getList( $numRows=1000000, $order="publicationDate DESC" ) {
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "SELECT SQL_CALC_FOUND_ROWS *, UNIX_TIMESTAMP(publicationDate) AS publicationDate FROM articles
ORDER BY " . mysql_escape_string($order) . " LIMIT :numRows";

$st = $conn->prepare( $sql );
$st->bindValue( ":numRows", $numRows, PDO::PARAM_INT );
$st->execute();
$list = array();

while ( $row = $st->fetch() ) {
$article = new Article( $row );
$list[] = $article;
}

// Now get the total number of articles that matched the criteria
$sql = "SELECT FOUND_ROWS() AS totalRows";
$totalRows = $conn->query( $sql )->fetch();
$conn = null;
return ( array ( "results" => $list, "totalRows" => $totalRows[0] ) );
}


/**
* Inserts the current Article object into the database, and sets its ID property.
*/

public function insert() {

// Does the Article object already have an ID?
if ( !is_null( $this->id ) ) trigger_error ( "Article::insert(): Attempt to insert an Article object that already has its ID property set (to $this->id).", E_USER_ERROR );

// Insert the Article
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "INSERT INTO articles ( publicationDate, title, summary, content ) VALUES ( FROM_UNIXTIME(:publicationDate), :title, :summary, :content )";
$st = $conn->prepare ( $sql );
$st->bindValue( ":publicationDate", $this->publicationDate, PDO::PARAM_INT );
$st->bindValue( ":title", $this->title, PDO::PARAM_STR );
$st->bindValue( ":summary", $this->summary, PDO::PARAM_STR );
$st->bindValue( ":content", $this->content, PDO::PARAM_STR );
$st->execute();
$this->id = $conn->lastInsertId();
$conn = null;
}


/**
* Updates the current Article object in the database.
*/

public function update() {

// Does the Article object have an ID?
if ( is_null( $this->id ) ) trigger_error ( "Article::update(): Attempt to update an Article object that does not have its ID property set.", E_USER_ERROR );

// Update the Article
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "UPDATE articles SET publicationDate=FROM_UNIXTIME(:publicationDate), title=:title, summary=:summary, content=:content WHERE id = :id";
$st = $conn->prepare ( $sql );
$st->bindValue( ":publicationDate", $this->publicationDate, PDO::PARAM_INT );
$st->bindValue( ":title", $this->title, PDO::PARAM_STR );
$st->bindValue( ":summary", $this->summary, PDO::PARAM_STR );
$st->bindValue( ":content", $this->content, PDO::PARAM_STR );
$st->bindValue( ":id", $this->id, PDO::PARAM_INT );
$st->execute();
$conn = null;
}


/**
* Deletes the current Article object from the database.
*/

public function delete() {

// Does the Article object have an ID?
if ( is_null( $this->id ) ) trigger_error ( "Article::delete(): Attempt to delete an Article object that does not have its ID property set.", E_USER_ERROR );

// Delete the Article
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$st = $conn->prepare ( "DELETE FROM articles WHERE id = :id LIMIT 1" );
$st->bindValue( ":id", $this->id, PDO::PARAM_INT );
$st->execute();
$conn = null;
}

}

?>

None there either. 190 lines of code
07-Feb-11 19:26
No idea then I'm afraid!

It looks like you're running it on Windows so you might need to make sure your files have Windows line endings rather than Mac/Unix. Other than that I can't think of what the problem might be, if you have no whitespace outside your <?php ... ?> tags.

You could remove the line:


ini_set( "display_errors", true );


...which will at least stop the error showing on the page. Not sure if your session will work then (it might).

Matt

--
Matt Doyle, Elated
07-Feb-11 20:05
Started with a fresh install and there are no errors. However sessions seem glitchy. For example after logging in I will log out and be taken to the admin homepage to add a new article, but if I click to add new article it will take me to the login form. If I click site admin without logging in I will be redirected to the admin home page again.
07-Feb-11 23:29
"Started with a fresh install and there are no errors" - A fresh install of XAMPP, or the CMS?

"However sessions seem glitchy" - Sounds like either a problem with your PHP install, or possibly your browser is caching stuff it shouldn't.

You could maybe try adding session_write_close() just before the header() calls in admin.php - this will force PHP to write the session data to disk at that point, which may work around some problem with PHP:

http://php.net/manual/en/function.session-write-close.php

Also take a look at the session file when you're logged in and out, and see if it contains the expected data. You can find the session folder with:


<?php echo session_save_path(); ?>


Cheers,
Matt

--
Matt Doyle, Elated
08-Mar-11 04:25
Hi,
I found this really useful and easy to understand so congrats.
However, when I try to click on the site admin to login I get an error message.
The error message reads:

Parse error: syntax error, unexpected T_IS_NOT_EQUAL, expecting ',' or ')' in C:\wamp\www\cms\admin.php on line

It's this piece of code thats giving me the problem.

if (isset( $_GET['action'] != "login") && $_GET['action'] != "logout" && !$_SESSION['username'] ) {
login();
exit;
}

Can you help?
Thank you
08-Mar-11 17:17
That's incredible training, Matt. What an awesome creation. Simple, and a fantastic learning device for designers who are new to PHP, like myself.

I wish there were 48 hours in one day and I could get by on only 4 hours of sleep.!

--
bunny spoons and cotton tails.
09-Mar-11 05:18
@cactus: Thanks! Your code should be:


if ( $_GET['action'] != "login" && $_GET['action'] != "logout" && !$_SESSION['username'] ) {
login();
exit;
}


@milkdoll: Thanks - the tutorial was quite a big project! I'm happy that people are finding it useful.

--
Matt Doyle, Elated
09-Mar-11 07:48
Tried deploying this source code in PHP 5.3.5 and WAMP 2.0 getting errors.
If i take cautious evaluation with isset($_GET['action']), then errors are gone, but if i attempt to add new article, it redirects to login page and am unable to proceed further,

Could you please check this and comment..

--
phpuser
09-Mar-11 09:13
phpuser is having pretty much the same problem as me.

I started off with the code that you originally said and found it gave the error undefined index action on line 6 (twice) and line 11 when I clicked on the log in button.
When I added in isset it gave me the previous error.
I tried your code which I assume was the same as in the tutorial and still get the undefined index error.

Any ideas?
09-Mar-11 16:32
@phpuser & @cactus: That's probably because you have error_reporting set to E_ALL in your php.ini. The default is (E_ALL ^ E_NOTICE).

A workaround is to exclude notices from your error reporting - add this to the top of your admin.php:


error_reporting(E_ALL ^ E_NOTICE);


I'll update the code to check that the action and username values are set, to avoid this issue.

@cactus: You got that other error because your code had a syntax error in it.

Cheers,
Matt

--
Matt Doyle, Elated
09-Mar-11 18:03
Article and code now updated. You can grab the latest code here:

http://www.elated.com/res/File/articles/development/php/cms-in-an-afternoon-php-mysql.zip

--
Matt Doyle, Elated
11-Mar-11 03:58
Thats solved it thanks a lot!!!
14-Mar-11 00:28
@cactus: Great stuff

--
Matt Doyle, Elated
21-Mar-11 23:29
Hey Matt...thanks a ton for this tutorial.

I have a question...everything works great except one thing for me.

For some reason, the date is incorrect on the index page. I changed the date to be:


date_default_timezone_set( "America/Los_Angeles" );

Which I found on this url: http://www.php.net/manual/en/timezones.php

I'm not quite sure where I'm going wrong.

Any suggestions?

Thanks!

Chris
22-Mar-11 18:08
Hi Chris,

How is the date incorrect? Is it a few hours out?

Did you change the timezone after creating some articles? If so then the articles would have been saved using the old timezone but their dates are being read using the new timezone, which might explain the difference.

--
Matt Doyle, Elated
22-Mar-11 18:28
Hey Matt,

Thanks for getting back to me so quickly!

The date currently shows 31 December 1969 for every post whether it's in the article archive or on the homepage.

I don't know where I'm going wrong. I checked to make sure in phpmyadmin that it's set to DATE like it should be and it is.

:/

Chris

- Amendment -

Actually...it looks like it shows "31 December" for the home page posts of articles and then on the article itself it says "PUBLISHED ON 31 DECEMBER 1969"

Then on the Article Archive it shows "31 December 1969" for every article (even if I post a new one now, it will still say that same date).

[Edited by christopherjc on 22-Mar-11 18:32]
22-Mar-11 18:51
Chris,

"31 December 1969" implies that the date is being passed from or to MySQL as zero or null (1 Jan 1970 is zero, minus a few hours to allow for your timezone difference).

I don't think this is a problem with timezones. It's a problem with the dates not being properly exchanged between PHP and MySQL.

The next step would be to look at your MySQL table using the mysql tool or phpMyAdmin to see if the dates are in the article records or not.

If you need any further help with your problem, please start a new topic:

http://www.elated.com/forums/authoring-and-programming/topic/new/

Cheers,
Matt

--
Matt Doyle, Elated
23-Mar-11 04:57
Hi matt,

Sorry to be a bit late...Thanks for the new code its working fine...

--
phpuser
23-Mar-11 12:59
Great script, one of the most useful things I could ever imagine to use outside of a forum source.

So as return I came here clicked ads on purpose, and was just wondering if you thought of developing a comment page to go with, as in after the user views the article he or she could comment on it.

I am currently in this very progress only on localhost though, but thanks for the source and your time sir, keep up the good work and God bless.

--
TBC...
25-Mar-11 23:36
@phpuser: Great stuff

@DuckNorris: Not a bad plan - maybe I'll write a follow-up article showing how to add comments. Thanks for the suggestion.

--
Matt Doyle, Elated
26-Mar-11 13:20
In all honesty I hate Wordpress, and cannot stand how popular it is same reason I do not own a .com domain.
(Just everything is so mainstream) [I rather stick out]
I just find if there was a basic underground script that could function as well as the giant Wordpress and even got more ideas for just this script...

User comments... They don't have to register or anything just have there a name field if not field name person, Anonymous hidden field for date input and their message, strip html tags, and add a very simple math function to avoid spam, cause robots can't do math... lol

Add a simple poll script for the users to only see on the main page, no log in required to vote, but not have their be a set cookie once on the url's homepage

(Optional) Registration This allows user(s) to suggest polls always be logged in and change the theme

These and more ideas are 'a float' in my mind, and I could really be developing them myself however I shared with you since you shared with me first, and for that I again have to say thanks.

--Daniel

--
TBC...
28-Mar-11 04:10
@Daniel: Thanks for your additional ideas. They'd all make interesting tutorials, so I'll add them to the list of possible future topics!

--
Matt Doyle, Elated
30-Mar-11 07:57
great script, and great tutorial

i just wan't to ask how to use this, if we wanna more tabs(with other type of news(sport, business,cars...)). i tried, and it shows me error


Fatal error: Class 'Vozac' not found in C:\xampp\htdocs\cms\takmicari.php on line 40



38. function vozaci() {
39. $results = array();
40. $data = Vozac::getList( VOZACI_NUM_VOZACI );
41. $results['vozaci'] = $data['results'];
42. $results['totalRows'] = $data['totalRows'];
43. $results['pageTitle'] = "Vozači";
44. require( TEMPLATE_PATH . "/vozaci.php" );
}


if you can help me, i would be really grateful
31-Mar-11 03:59
@adiomb: It sounds like you forgot to include your Vozac (Article?) class file at the top of your script.

If you need more help with creating multiple tabs (categories?) then please post your questions in a new topic:

http://www.elated.com/forums/authoring-and-programming/topic/new/

Cheers,
Matt

--
Matt Doyle, Elated
31-Mar-11 09:11
i fix this problem, now it s ok, thank you
but i have another problem, when i want to add new post, it says it is successfully added but it doesn't aper in db nor on page.
04-Apr-11 02:23
@adiomb: Have a look in your PHP error log. You might find some clue there.

If you need any further help with your CMS please post in a new topic:

http://www.elated.com/forums/authoring-and-programming/topic/new/

Thanks,
Matt

--
Matt Doyle, Elated
08-Apr-11 05:05
i have problems with characters č,ć,đ,š, somewhere they, somewhere they don't, i remove htmlspecialchars filter from entire code, and they won't to appear, again. in db in thepalcecharacters, there are question-mark "?" and characters like this "Å¡

other question is how can i make in news to appear month on my language. Instead of January to appear Januar, and so on...
11-Apr-11 00:33
@adiomb: Sounds like you have a Unicode/UTF-8 issue. Put this meta element in your page's head section:


<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />


Also, make sure your MySQL table and connection use utf8:

http://www.bluetwanger.de/blog/2006/11/20/mysql-and-utf-8-no-more-question-marks/

Cheers,
Matt

--
Matt Doyle, Elated
12-Apr-11 11:01
Absolutely great tutorial. Works a dream on my local set-up, thanks!

Would you be able to explain what would be required to upload images to the database?

That would be really really useful!
14-Apr-11 07:08
@m4xjb: Thanks - glad you enjoyed it.

To do image uploads, in a nutshell:

- Add enctype="multipart/form-data" to your form tag.

- Add an <input type="file"> field to your form.

- Use the PHP $_FILES array to retrieve information about your uploaded image(s), and process it/them: http://www.php.net/manual/en/features.file-upload.post-method.php

Hope that helps! Let us know if you'd like more info.

--
Matt Doyle, Elated
16-Apr-11 12:32
Thanks matt! Found it a bit tricky extrapolating the php.net page to this example. I'm getting there but not quite... Here is progress so far:

I've added the input and label to the form in editArticle.php

In Article.php I have:
1) Added the property $image in the article class.

2) Created and populated an image object in __construct() with:

if ( isset( $_FILES['image']['tmp_name'])) $this->image = $data['image'];


3) Added the image to the article table by adding this to insert() and update():

$st->bindValue( ":image", $this->image);


4) And finally added the image to viewArticle.php:

<img src="<?php $article->image )?>" alt="article image">


Have I covered everything? Albeit incorrectly!

I'm sure I'm creating the image object in __construct() wrong.
Also, I'm confused with adding the image to the article table with insert() and update(). As the image not a string or an integer, what alternative do I use for PDO::PARAM_???

Atm I'm getting an 'Undefined index' error message in the browser.

Any help is really appreciated. Can't wait to adjust the code to my own needs once it's all up and running

Cheers!
18-Apr-11 06:37
What you've done certainly looks correct off the top of my head. But you'll also need to use the PHP move_uploaded_file() function to move the uploaded file from the temp folder to a folder within your website (eg "/images"). Then your markup would be:


<img src="/images/<?php $article->image )?>" alt="article image">


It's also wise to use is_uploaded_file() to check that the file was actually uploaded by the user (for security reasons).

http://www.php.net/manual/en/function.move-uploaded-file.php

http://www.php.net/manual/en/function.is-uploaded-file.php

"I'm sure I'm creating the image object in __construct() wrong.
Also, I'm confused with adding the image to the article table with insert() and update(). As the image not a string or an integer, what alternative do I use for PDO::PARAM_???"

You shouldn't add the image to the database! It's possible (using BLOBs), but it's much easier and more efficient to store the image file in a folder on your website, and just store the image's filename in the DB (which I think is what your code will do, although I haven't checked it). The image filename is of course a string.

Cheers,
Matt

[Edited by matt on 18-Apr-11 06:37]

--
Matt Doyle, Elated
19-Apr-11 09:19
Thanks matt,

Ok, so using $_FILES in __construct() is correct? I thought I maybe should have used $data like the rest of the objects.

Then I should use PDO::PARAM_STR in the insert() and update() functions to store the image filename in the database... In that case I need an image field in tables.sql. So for this I used data type: varchar(255) NOT NULL. Does that seem ok?

And after that line - still within insert() and/or update() - I add the move_uploaded_file() function like so:


$target_path = "images/";
$target_path = $target_path . basename( $_FILES['image']['name']);
move_uploaded_file($_FILES['image']['tmp_name'], $target_path)


Where 'image' is the name of the <input>. But I'm getting an error saying that the 'image' is undefined

Again, any help is much appreciated! I'm hoping that others will benefit from this too
20-Apr-11 03:17
@m4xjb: $_FILES['image'] contains all the info about the uploaded image (assuming your file upload field is called "image"). I'm not sure what $data['image'] holds without seeing all of your script. It might help if you called your property something like $imageFilename instead of $image, to avoid confusing it with the "image" file upload field and $_FILES['image'] element. You can populate $imageFilename from $_FILES['image']['name'].

varchar(255) should be fine for storing the image filename.

'image' is undefined implies that the user didn't upload an image when they submitted the form. (Presumably it's an optional field?) You need to check that $_FILES['image'] exists before you try to access any of its elements, call move_uploaded file(), etc:


if ( isset($_FILES['image']) ) { ... }


Also, note that $target_path needs to be the full path to the images folder (from the volume root). eg /home/username/website/htdocs/images.

--
Matt Doyle, Elated
24-Apr-11 12:44
Hi matt
this is just a great script

but i got error
i just installed the script on wamp
but when i open i got this error

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[28000] [1045] Access denied for user 'usman'@'localhost' (using password: YES)' in C:\wamp\www\classes\Article.php on line 103

PDOException: SQLSTATE[28000] [1045] Access denied for user 'usman'@'localhost' (using password: YES) in C:\wamp\www\classes\Article.php on line 103


Can u plz tell what this error
plzzzzz solve my problem plz

Thanx,Usman
25-Apr-11 04:49
Hi Usman,

That error means that your PHP script couldn't access your MySQL database using the username/password that you put in your script.

Make sure the username, password, and database name in the script exactly match those in your MySQL database. Also make sure that you have created the MySQL user and password correctly, and given the user permission to read and modify your articles table.

--
Matt Doyle, Elated
25-Apr-11 08:18
I did understand that
can u tell what to write in these places

DB_DSN", /// Here I have to write "localhost"
dbname //// Here My Database Name
DB_USERNAME///// What To Write Here
DB_PASSWORD //////What To Wirte Here

plzzzzz help
26-Apr-11 16:30
hi, it is me again
i created few more tabs, working on the same structure, everything works except archive and viewVozac... when i click on specific news it returns me to the homepage(index) and in navigation bar it writes
http://localhost/cms/?action=archiveVideo?http://localhost/cms/action=viewVozac&vozacId=50
but doesn't show archive or article(vozac in this example) i checked everything many times, but i can't find where i making mistake
thanks in advance
28-Apr-11 06:27
@usman ikram: Yes, you need to put your MySQL database name, database username, and database password in those constants.

@adiomb: Please post your whole index.php script in a new topic so we can take a proper look:

http://www.elated.com/forums/authoring-and-programming/topic/new/

Matt

--
Matt Doyle, Elated
30-Apr-11 16:40
Help! I can't get past the first part!

I created the database and the schema, but when I try to add the Schema into mysql I get this error message:


"ERROR 064 (42000) at line 2: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(id))' at line 9."

I have no idea what I'm doing wrong as I've literally directly copied and pasted the code that was given.

Can anyone advise?
02-May-11 02:11
Oops! A comma was missing in the table schema in the article. (The code download is correct.)


content mediumtext NOT NULL


should be:


content mediumtext NOT NULL,


I've fixed up the article now. Let me know if you encounter any further problems.

Thanks!
Matt

--
Matt Doyle, Elated
10-May-11 03:06
First, thank for make a good tutorial for the beginner.You did great thing.
So this is the point.
1.Pagination

I can retrieve the data from database and pagination the data .
But i did the whole thing in one file but i don't know how to embed my code in your schema.

2.Categories

Here is the some problem. I got a umlimited subcategories class and it work very well. When i want to expand the functionality of your schema, the same problem came again. I have no idea how to do.

3.Maybe i just don't understand your schema that further and i am a new guy.
What i know is :
user->action->script function->class function
->script function ->templates ->user

like mvc ?

End: give me some advices as soon as possible.
Thank very much.
20-May-11 06:53
nice tutorial for beginner like me , it is realy helpful but please i would like to paginate my articles.how is this possible and please can u send me the codes for doing this? thanks a lot.
23-May-11 02:22
@olubee: The basic idea behind pagination is:

1) Use the MySQL LIMIT clause to return just the articles for the current page: http://dev.mysql.com/doc/refman/5.0/en/select.html

2) Use SQL_CALC_FOUND_ROWS and FOUND_ROWS() to retrieve the total number of articles in the table

3) Use the above information to calculate the start row positions for each page

4) Display the article list, along with links to other pages

--
Matt Doyle, Elated
24-May-11 03:36
I am download this cms and run on local but I have this error when go to index.php



Fatal error: Uncaught exception 'PDOException' with message 'could not find driver' in C:\Program Files\EasyPHP5.3.0\www\cms-in-an-afternoon-php-mysql\classes\Article.php:103 Stack trace: #0 C:\Program Files\EasyPHP5.3.0\www\cms-in-an-afternoon-php-mysql\classes\Article.php(103): PDO->__construct('mysql:host=loca...', 'root', '') #1 C:\Program Files\EasyPHP5.3.0\www\cms-in-an-afternoon-php-mysql\index.php(40): Article::getList(5) #2 C:\Program Files\EasyPHP5.3.0\www\cms-in-an-afternoon-php-mysql\index.php(14): homepage() #3 {main} thrown in C:\Program Files\EasyPHP5.3.0\www\cms-in-an-afternoon-php-mysql\classes\Article.php on line 103


please help me, I am using Easyphp on my local
24-May-11 04:03
@alisoftware: See http://www.easyphp.org/forums/9/145328/php_and_mysql_-

Or use XAMPP instead:

http://www.apachefriends.org/en/xampp.html

--
Matt Doyle, Elated
24-May-11 04:25
are you sure solve my problem with XAMPP?

Because I have same problem with other cms and do not have problem with other else such as Datalife Engine or other Popular cms

And I have a request (maybe question!!), how can I add comments section to this cms?

[Edited by alisoftware on 24-May-11 04:27]
03-Jun-11 18:50
hello, i'm having a problem with it escaping the code
i type in the correct link code or img code and it comes out like

<a href=\"http://website.com\">hi</a>

could you please tell me how to fix this?

using apache2/mysql/php5 on linux


thank you,
07-Jun-11 07:11
@jasonh_000: You mean the slashes? Looks like you have magic quotes enabled - turn the feature off:

http://php.net/manual/en/security.magicquotes.php

--
Matt Doyle, Elated
07-Jun-11 17:29
thanks, even though in my only php.ini and my other .ini and .conf files i had this turned off, it was still using it.

so i toggeled it off via .htaccess

thanks for the script and for the reply to my issue.
14-Jun-11 02:36
Hi Matt,

This is a great tutorial so thanks for sharing your knowledge!

I noticed something interesting after I updated my Browsers – the Save Changes button no longer works when saving a NEW article...all other buttons work, and you can edit and re-save an existing article fine, but when adding a new article the Save Changes button does nothing – you keep clicking it and the article doesn’t save.

This is the case in Mozilla 4, and Google Chrome 12.0.742.91 but was fine in all previous versions.

It still works OK in Internet Explorer 9 though.

Just something odd I thought I would bring to your attention, if you have any thoughts!

Thanks again,

Chris
15-Jun-11 11:58
i have problem with picture upload when editing article, when adding new article, it works

this is code from class Article:



public $slika = null;

if ( isset( $data['slika'] ) ) $this->slika = $data['slika'];

/**
* Inserts the current Article object into the database, and sets its ID property.
*/

public function insert() {

// Does the Article object already have an ID?
if ( !is_null( $this->id ) ) trigger_error ( "Article::insert(): Attempt to insert an Article object that already has its ID property set (to $this->id).", E_USER_ERROR );

// Insert the Article
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$slikica = $_SESSION['s'];
$sql = "INSERT INTO articles ( publicationDate, title, summary, content, slika ) VALUES ( FROM_UNIXTIME('$this->publicationDate'), '$this->title', '$this->summary', '$this->content', '$slikica' )";
$st = $conn->prepare ( $sql );

$st->execute();
$this->id = $conn->lastInsertId();
$conn = null;
}


/**
* Updates the current Article object in the database.
*/

public function update() {

// Does the Article object have an ID?
if ( is_null( $this->id ) ) trigger_error ( "Article::update(): Attempt to update an Article object that does not have its ID property set.", E_USER_ERROR );

// Update the Article
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$slikica = $_SESSION['s'];
$sql = "UPDATE articles SET publicationDate=FROM_UNIXTIME('$this->publicationDate'), title='$this->title', summary='$this->summary', content='$this->content', slika='$slikica' WHERE id = '$this->id'";
$st = $conn->prepare ( $sql );
$st->execute();

$conn = null;
}






and code from admin.php



function editArticle() {

$results = array();
$results['pageTitle'] = "Mijenjaj vijest";
$results['formAction'] = "editArticle";

if ( isset( $_POST['saveChanges'] ) ) {

// User has posted the article edit form: save the new article
$article = new Article;
$article->storeFormValues( $_POST );

//define a maxim size for the uploaded images
define ("MAX_SIZE","1000");
// define the width and height for the thumbnail
// note that theese dimmensions are considered the maximum dimmension and are not fixed,
// because we have to keep the image ratio intact or it will be deformed
define ("WIDTH","412");
define ("HEIGHT","324");

// this is the function that will create the thumbnail image from the uploaded image
// the resize will be done considering the width and height defined, but without deforming the image
function make_thumb($img_name,$filename,$new_w,$new_h)
{
//get image extension.
$ext=getExtension($img_name);
//creates the new image using the appropriate function from gd library
if(!strcmp("jpg",$ext) || !strcmp("jpeg",$ext))
$src_img=imagecreatefromjpeg($img_name);

if(!strcmp("png",$ext))
$src_img=imagecreatefrompng($img_name);

//gets the dimmensions of the image
$old_x=imageSX($src_img);
$old_y=imageSY($src_img);

// next we will calculate the new dimmensions for the thumbnail image
// the next steps will be taken:
// 1. calculate the ratio by dividing the old dimmensions with the new ones
// 2. if the ratio for the width is higher, the width will remain the one define in WIDTH variable
// and the height will be calculated so the image ratio will not change
// 3. otherwise we will use the height ratio for the image
// as a result, only one of the dimmensions will be from the fixed ones
$ratio1=$old_x/$new_w;
$ratio2=$old_y/$new_h;
if($ratio1<$ratio2) {

$thumb_w=$new_w;
$thumb_h=$old_y/$ratio1;

}
else {

$thumb_h=$new_h;
$thumb_w=$old_x/$ratio2;
}

// we create a new image with the new dimmensions
$dst_img=ImageCreateTrueColor($thumb_w,$thumb_h);

// resize the big image to the new created one
imagecopyresampled($dst_img,$src_img,0,0,0,0,$thumb_w,$thumb_h,$old_x,$old_y);

// output the created image to the file. Now we will have the thumbnail into the file named by $filename
if(!strcmp("png",$ext))
imagepng($dst_img,$filename);
else
imagejpeg($dst_img,$filename);

//destroys source and destination images.
imagedestroy($dst_img);
imagedestroy($src_img);
}

// This function reads the extension of the file.
// It is used to determine if the file is an image by checking the extension.
function getExtension($str) {
$i = strrpos($str,".");
if (!$i) { return ""; }
$l = strlen($str) - $i;
$ext = substr($str,$i+1,$l);
return $ext;
}

// This variable is used as a flag. The value is initialized with 0 (meaning no error found)
//and it will be changed to 1 if an errro occures. If the error occures the file will not be uploaded.
$errors=0;
// checks if the form has been submitted
if(isset($_POST['saveChanges']))
{
//reads the name of the file the user submitted for uploading
$image=$_FILES['image']['name'];
// if it is not empty
if ($image)
{
// get the original name of the file from the clients machine
$filename = stripslashes($_FILES['image']['name']);

// get the extension of the file in a lower case format
$extension = getExtension($filename);
$extension = strtolower($extension);
// if it is not a known extension, we will suppose it is an error, print an error message
//and will not upload the file, otherwise we continue
if (($extension != "jpg") && ($extension != "jpeg") && ($extension != "png"))
{
print "<script type='text/javascript'> alert('Nepoznata ekstenzija!!');</script>";

$errors=1;
}
else
{
// get the size of the image in bytes
// $_FILES[\'image\'][\'tmp_name\'] is the temporary filename of the file in which the uploaded file was stored on the server
$size=getimagesize($_FILES['image']['tmp_name']);
$sizekb=filesize($_FILES['image']['tmp_name']);

//compare the size with the maxim size we defined and print error if bigger
//if ($sizekb > MAX_SIZE*1024)
//{

//$errors=1;
//}

//we will give an unique name, for example the time in unix time format
$image_name=time().'.'.$extension;
//the new name will be containing the full path where will be stored (images folder)
$newname="images/".$image_name;
$copied = copy($_FILES['image']['tmp_name'], $newname);
//we verify if the image has been uploaded, and print error instead
if (!$copied)
{

print "<script type='text/javascript'> alert('Kopiranje slike neuspjesno!!');</script>";
$errors=1;
}
else
{
// the new thumbnail image will be placed in images/thumbs/ folder
$thumb_name='images/thumbs/thumb_'.$image_name;
// call the function that will create the thumbnail. The function will get as parameters
//the image name, the thumbnail name and the width and height desired for the thumbnail
$thumb=make_thumb($newname,$thumb_name,WIDTH,HEIGHT);
}} }}

//If no errors registred, print the success message and show the thumbnail image created



$postArray = &$_POST ; // 4.1.0 or later, use $_POST


foreach ( $postArray as $sForm => $value )
{
if ( get_magic_quotes_gpc() )
$postedValue = htmlspecialchars( stripslashes( $value ) ) ;
else
$postedValue = htmlspecialchars( $value ) ;

}


$_SESSION['s']=$image_name;
$article->insert();
header( "Location: admin.php?status=changesSaved" );

} elseif ( isset( $_POST['cancel'] ) ) {

// User has cancelled their edits: return to the article list
header( "Location: admin.php" );
} else {

// User has not posted the article edit form yet: display the form
$results['article'] = new Article;
require( TEMPLATE_PATH . "/admin/editArticle.php" );
}

}
23-Jun-11 03:26
@ChrisJ: No problem! I can't reproduce your bug though. Just tested using Chrome 12.0.742.100 and Firefox 4.0.1 (Mac) and I could save new articles every time.

Maybe there's something about your setup that's causing the problem? Have you tried looking in your browser error consoles?

Cheers,
Matt

--
Matt Doyle, Elated
29-Jun-11 17:52
Hi,
I'm still learning PHP. This tutorial is of great help for me. The only problem is: in German we have umlauts like ä ö ü ß and Ä Ö Ü. This CMS swallows all umlauts, in text and in title. How to keep the umlauts?
30-Jun-11 17:38
The solution is:
1. ensure that your web server is sending the correct content-type header:
Content-Type: text/html; charset=utf-8
(you can send this header also at the beginning of a php script)
2. change the preg_replace command in Article.php to:
preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9äöüßÄÖÜ()]/", "", $data['title'] );
01-Jul-11 01:12
@Gerhard: Thanks for your solution. I forgot to allow for accented characters in the regular expression. Good catch! I expect a more flexible regular expression is needed here...

--
Matt Doyle, Elated
07-Jul-11 05:08
hey how is it going, let me first start of by saying thank you i was searching for atleast 12 hours trying to find one of these and finally found a great one! the only problem is, how can you add like embed youtube videos in the content secion, so if its a tutorial or something, also if you could just give me a little help for some reason wen ever i add 2 posts it goes out of order. please get back as soon as its a good time for you.
thanks
12-Jul-11 02:10
@envizionx: Just find your video on YouTube, click Share, click Embed, and copy/paste the iframe markup into your content field.

The posts are in reverse date order (newest first). You can change this in the Article class's getList() method.

--
Matt Doyle, Elated
12-Jul-11 10:30
Great tutorial, I've got it started and am already modifying it for my purposes with no problems!

Now I'm thinking of how to make the installation more secure in addition to the security tips you already posted. What do you think of securing config.php using .htaccess as shown with the code below?



<Files config.php>
Order Allow,Deny
Deny from all
</Files>
13-Jul-11 04:43
@ANA Designs: That should work, provided your Apache server is set up correctly. Give it a go!

To be even safer, move your config.php outside the document root.

--
Matt Doyle, Elated
30-Aug-11 20:26
Could someone tell me how much of this I would have to change if I were to do the tutorial on a Windows machine?
Thanks.
01-Sep-11 21:24
Awesome tut - huge thanks, Matt.

Cheers,

Phil.
02-Sep-11 02:23
@Chett: Hardly anything, I'd have thought.

@bionic frog: You're welcome - glad you liked it!

--
Matt Doyle, Elated
13-Sep-11 14:00
Thank you SO MUCH, Sir Doyle!

This is one of the most clearly explained, concise tutorials I've ever read. I'm working on a php site, and I'm new to php in general and very new to OOP. I wish I'd found this tutorial ages ago when I first started learning php and working with Wordpress. This tutorial should be recommended to anyone who wants to work with Wordpress or any php-based CMS, as it is a simplified example of how such a system works. The site I'm currently developing is simple and from scratch, and this article has helped bridged the gap between what I'm now trying to do and what I've seen done in complex CMSs.

Again, many, many thanks. You have made my life a bit easier.

- Emily
14-Sep-11 14:33
Hi All,

Just to let you guys know - I was that impressed with this tutorial, I invested in Matt's book "Beginning PHP 5.3".

It is excellent - definitely worth the money. If you're new(ish) to PHP like I am, the book is worth it's weight in gold.

Everything is explained in simple to understand terms and the books covers the right amount of subjects for anyone starting out in PHP coding.

Well done Matt on a great book - many thanks

bionic frog

P.S. Matt hasn't paid me for this post...
15-Sep-11 02:44
@esommer: Thanks for your kind words. Yes, most CMS work in the same basic way, even if they (usually!) have lots of extra features. I'm glad my tutorial helped explain the concepts.

@bionic frog: Thanks so much for buying my PHP book and recommending it - I really appreciate it.

--
Matt Doyle, Elated
30-Sep-11 09:23
When I post an exterior link in the content of an article, it wraps the domain with \ and slaps the local domain on the links as well.

So when I link to a href="http://www.external.com" it turns it into a href="http://www.cms.com/\"http://www.external.com\"

I tried disabling magic quotes by creating an .htaccess file and putting:

php_flag magic_quotes_gpc Off

in the file, but the site then produces an internal server error. Any suggestions? I'm using a third-party server.

Thanks!
01-Oct-11 05:46
Hi Matt.
I'm developing a CMS that in short I wiil upload to a hoster.
Following your detailed CMS, congratulations, I've added some changes. The most important is that users may, and that's the point, write their articles, so I created an user form for them to do so, althought they can't change or delete the already stocked in DB.

The purpose of the site is to compile the history of a proffesional group that is almost 60 years old, narrated by it's members, so I expect many entries over the next year.
Now my request.

First, I soon will need to paginate by years, from 1952 y 2012.
I saw in your "Build a CMS in an Afternoon..." forum your response to a member, but it´s not so easy for me to implement.
Seccond, I'd like to secure the site a little bit more.
Could you help?
So many thanks.
04-Oct-11 23:19
@Sparkus: Works fine for me on my dev server, so I'm assuming it's something strange about your server setup. Maybe there's a security script running that is attempting to sanitize all URLs or something?

Also you can check if magic quotes is actually off at runtime using http://php.net/manual/en/function.get-magic-quotes-gpc.php .

--
Matt Doyle, Elated
05-Oct-11 00:20
@mar: I can't go into detail about pagination here. I might write a follow-up article on pagination and other topics however.

Not sure what you mean about "securing the site". If you have specific questions on securing websites, please post a new topic here:

http://www.elated.com/forums/authoring-and-programming/topic/new/

--
Matt Doyle, Elated
05-Oct-11 08:09
@Matt: Thanks for the reply. Perhaps it is because I have the cms currently installed in a subfolder of a directory that is a root for a WordPress install. I used the cms with an addon domain. Is that known to cause problems?

Should I host them on separate hosting accounts? Perhaps I should put them both in a separate subdirectory and point to each using an addon domain so one is not under the other.
06-Oct-11 02:37
OK matt. Thanks.
While expecting for your follow-up article, I'll try to find some info in the www. Same for security.
Thanks again.
06-Oct-11 03:19
@Sparkus: No idea I'm afraid. I'd start by creating a separate website if possible (perhaps locally) and installing an identical copy of CMS code there, just to rule out problems with the code. If it works OK then start digging into your server/PHP config a bit more.

Did you run get_magic_quotes_gpc() to see if magic quotes is on at runtime or not?

--
Matt Doyle, Elated
06-Oct-11 15:30
Hi Matt, I just wanted to say that I would also appreciate if you did a piece on pagination for this cms. I'm new to php but I can get it to work on stand-alone scripts if you know what I mean.
11-Oct-11 05:49
thank you....
20-Oct-11 13:42
That was a splendiferous tutorial and works very well. I was just wondering, I've integrated the AJAX Comments System from http://tutorialzine.com/2010/06/simple-ajax-commenting-system/ but it's set up so that I'm accessing the Comments table directly from the viewArticle.php page. Does that kind of defeat the entire purpose of the schema or does it really matter too much?
25-Oct-11 10:04
@Matt: Finally got around to running the magic quotes test and it returned a 1, which means they are on.

Guess I'll have to contact my server host to turn them off or apply a workaround to the CMS code.
26-Oct-11 04:06
@DOC: I don't understand the question I'm afraid. Also I'm not familiar with that comments system. However if it works and it's not causing any problems then I'd leave it as it is!

@Sparkus: Just run stripslashes() on the posted content from within Article:storeFormValues(). For example (not tested!):


public function storeFormValues ( $params ) {

if ( get_magic_quotes_gpc() ) $params['content'] = stripslashes( $params['content'] );

// Store all the parameters
$this->__construct( $params );

...


--
Matt Doyle, Elated
31-Oct-11 17:49
I downloaded your code and followed the tutorial but I must be missing something. the cms folder is in my htdocs folder.
I then create the database cms in XAMPP then what's the next step? I'm a little stuck as after doing this I try and open the php files and I see this. Is there something else I need to do?

title . " | Widget News"; require( TEMPLATE_PATH . "/viewArticle.php" ); } function homepage() { $results = array(); $data = Article::getList( HOMEPAGE_NUM_ARTICLES ); $results['articles'] = $data['results']; $results['totalRows'] = $data['totalRows']; $results['pageTitle'] = "Widget News"; require( TEMPLATE_PATH . "/homepage.php" ); } ?>

Is it permissions or something, hope I don't sound like an idiot as this is helping my basic understanding of php and mysql greatly.
31-Oct-11 18:24
What a noob I didn't add the username and password to the database! Keep up the good work Matt!
02-Nov-11 03:07
@Matt8: Glad you got it working

--
Matt Doyle, Elated
08-Nov-11 06:54
Hey Matt

What's the best way to add an image upload facility to this, do you have any links?, I've searched online but can't find anything useful.

Also what's the easiest way to have multiple pages which can be edited? Would I recopy the entire code and the files and folders and just rename homepage in php code to something else like "newpage".
11-Nov-11 03:35
@Matt8: Check out http://www.php.net/manual/en/features.file-upload.post-method.php for info on adding a file upload feature using PHP. It's fairly straightforward. Exactly how you do it depends on how you want the CMS to work. One common way is to have a separate image upload feature that uploads the image to an images folder, then the user adds an img tag within the article, referencing the uploaded image URL. Rich text editors such as http://ckeditor.com/ and http://www.tinymce.com/ can make the process easier / smoother.

Not sure I understand your second question. You can already create and edit multiple articles using the CMS in the tutorial.

Cheers,
Matt

--
Matt Doyle, Elated
15-Nov-11 23:34
hi friends,

any one can help me to create a cms using these coding for the following template please....??
http://1solutionmy.com/cms/

regards..

I downloaded and follow this code to create a cms. its working fine.. very simple and smooth coding and design..
But I could not use use with another cms template...

[Edited by riffaz on 15-Nov-11 23:39]
18-Nov-11 05:51
Hi,
Great job.
I without any knowledge in CMS , MySql and PHP, i manage to follow your tutorial. Indeed a great article.

But i have same problem:

http://localhost/cms2/index.php - work fine
but when i click on the article its shows the root directory
http://localhost/cms2/?action=viewArticle&articleId=1

it suppose to be
http://localhost/cms2/index.php?action=viewArticle&articleId=1

how to correct this.

I change nothing at your codes.
Thanks
19-Nov-11 08:26
Hi,

Great article, I have followed everything to the letter, but for some reason when I go to my url I get the following error...

Fatal error: Class 'PDO' not found in apache2\htdocs\classes\Article.php on line 103

Does anyone have any idea what ive done wrong?

Thanks!
19-Nov-11 09:05
@matt2002 I'm no guru but maybe it has to do with enabling PDO in your php.ini file....you may have done some fussing around with this file already. Try adding these lines to the file:

extension=pdo.so
extension=pdo_sqlite.so
extension=sqlite.so
extension=pdo_mysql.so

Someone tell me if I'm steering this guy in the complete wrong direction.
19-Nov-11 09:13
@DOC Thanks for the suggestion, I just tried that and also
extension=pdo.dll
extension=pdo_sqlite.dll
extension=sqlite.dll
extension=pdo_mysql.dll

as I'm running on windows, but still getting 403, want this to work so bad!!!
19-Nov-11 12:14
http://localhost/cms2/?action=viewArticle&articleId=1

this cause an error when reading the article.

If i manually type this

http://localhost/cms2/index.php?action=viewArticle&articleId=1

its works fine.

What is the problem?
Why the link generated is wrong?
How to rectify this?
20-Nov-11 18:07
Hi,

This was a great article and it really helped me, but I am current having two issues.

One of which is on the homepage.php it is not showing any articles, even though I have entered some into the database and I can't seem to find any errors.

Second I am receiving this error:

"Forbidden

You don't have permission to access /cms/templates/ on this server.

Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request."

When I am trying to access the link on the home page to the article archive.

Thanks.
21-Nov-11 03:46
Hi,

I managed to resolve my previous issue by re-installing php. However I am now trying to create a line in the header which will use the article ID to create a menu along the top, however I have tried this...



<?php if (isset($results['articles'])) if(is_array($results['articles']))
foreach ( $results['articles'] as $article ) { ?>
<li><a href=".?action=viewArticle&amp;articleId=<?php echo $article->id?>"><?php echo htmlspecialchars( $article->title )?></a></li>
<?php } ?>


but it doesn't work on all pages only the homepage.php, when I drill down into an article the menu doesn't show and i get the following error

Notice: Undefined index: articles in \apache2\htdocs\templates\include\header.php on line 12

Warning: Invalid argument supplied for foreach() in \apache2\htdocs\templates\include\header.php on line 12

- any ideas?
21-Nov-11 23:47
@ramkumar: http://localhost/cms2/?action=viewArticle&articleId=1 should work if your web server is correctly configured to recognize index.php as an index file.

If you want, you can change '.' to 'index.php' in all the page templates, eg:


<a href=".?action=viewArticle...


to:


<a href="index.php?action=viewArticle...


Or for more flexibility, create a constant in config.php holding the index page URL (e.g. '.' or 'index.php'), then change the templates to use this constant throughout the CMS.

--
Matt Doyle, Elated
22-Nov-11 00:16
@matt2002: To do that you'll need to include the lines of code in viewArticle() in index.php to retrieve all the articles, like in the archive() and homepage() functions:


$data = Article::getList();
$results['articles'] = $data['results'];


--
Matt Doyle, Elated
22-Nov-11 04:33
I must admit, all those errors are due to web server error (index.php was not included). Thanks alot. Problem solved.
23-Nov-11 20:33
@cjcarey: You shouldn't be trying to access /cms/templates/ in your browser.

Are the articles in your database?

--
Matt Doyle, Elated
24-Nov-11 00:28
Awesome. Thanks for explaining the code step by step. I'm totally new to PHP/Basically everything so it really helped me out understanding what each step was actually doing. I have a question (possibly stupid). It is possible to have the CMS displayed to the user in a website I already created? Like inside a specific div on a page instead of having its own page?
24-Nov-11 02:41
Nevermind I figured it out. Thanks again for this. Really well done.
25-Nov-11 04:30
Hi,
Thank you for the tutorial.

but I have problem when I click on the article archive it shows http://www.gtmi.co.uk/cms/?action=archive and when I view articles it shows http://www.gtmi.co.uk/cms/?action=viewArticle&articleId=2

how can I correct this. Any help appriciated.
25-Nov-11 04:53
@QWCW11: Glad you got it working!

@ket_mit: See my answer to @ramkumar above.

--
Matt Doyle, Elated
25-Nov-11 07:37
Hey I'm wondering if anyone here would know how to apply a mod_rewrite to get a pretier url for each article. What I tried was



RewriteEngine On
RewriteRule ^articles/([^/]+)/?$ ?action=viewArticle.php?articleId=$1 [L]



...but I'm new and clueless with this Apache stuff so I'm not surprised it doesn't work.
26-Nov-11 02:34
@DOC: Looks pretty close. Try this:


RewriteRule ^articles/([^/]+)/?$ /?action=viewArticle&articleId=$1 [L]


--
Matt Doyle, Elated
26-Nov-11 17:30
Great Thanks for the Great Work Done Here, Very Very Nice Article With Great references and resources
28-Nov-11 20:00
Kudos for a great tutorial!! I have learned a lot from it and continue to learn.

My trouble is I am using it to take notes on my web site development lessons. When I try to add html code to contents it doesn't show up in the viewed article but when I look at what is stored in on my server it is there.

What can I do to display my notes for example :

<html> is the tag at the top of the code.

Thanks for the help.

[Edited by digiguy on 28-Nov-11 20:01]
29-Nov-11 06:22
Thanks very much for your tutorial which I've just got working, next step is to tailor it to my own needs.

Just a couple of points...

Might be worth mentioning that when adding an article, the Publication Date has to be in the following format YYYY-MM-DD, it took me a few goes before working this out.

Secondly, has anyone sorted out the use of hash() to mask passowords. I've gone to the link provided but can't quite make sense of it.
Thanks
Rog
01-Dec-11 03:10
@digiguy: The CMS is designed to output the HTML exactly as you enter it. So if you enter eg <p> then the CMS will display <p> in the article page, which the browser renders as a paragraph.

I get round this by HTML-encoding all angle brackets in my article content as I enter it. So <p> would become &lt;p&gt;. It's a bit of a pain, but you can easily do a search-and-replace in a text editor then paste the result into the CMS.

There are other ways round it too, like using CDATA.

Or you could make the CMS HTML-encode the article content when displaying it, using http://php.net/manual/en/function.htmlentities.php . But then you wouldn't be able to create actual rendered HTML elements (p, span, div, ul/li etc) in your content, since all your tags would be HTML-encoded automatically.

--
Matt Doyle, Elated
01-Dec-11 03:42
@wolfenr:

1. It does this already using an HTML5 placeholder (though you need to have a browser that supports placeholders).

2. hash() generates a unique one-way hash string based on the supplied plaint-text string (a password in this case). This hash is always the same for any given string. So you first hash the password you want to use, and the store the resulting hash string in a variable in config.php (eg $hashedAdminPassword). Then when the admin attempts to log in, you pass their supplied password through hash(). If the resulting string matches $hashedAdminPassword then you know they entered the correct password.

It is impossible (or at least very, very, very hard) to work out the original plain-text password from the hash. So it's a fairly secure way to store a password in a config file.

Cheers,
Matt

--
Matt Doyle, Elated
01-Dec-11 21:06
Matt, your a genius... okay maybe just a bloody good programmer.

I see what you are saying. Truthfully I had to try out the "htmlentities" and as I said, I see what your saying. I will try out your solution as that does make a lot of sense.

Don't know what CDATA is so I can't look into that.

All in all this is meant to be a learning tool and you have done it. I am learning!


Thanks a bunch!
02-Dec-11 17:15
I have everything up and running, and have even restyled everything to fit in to my current site, however, when I save an article, anywhere quotations are use, I get something that looks like the following.

"front motor plate\\\\\\\'s thickness. " For example.

Everytime I edit the article, more are added. It automatically breaks any link or IMG tag as well. I'm sure this is a document encoding issue, but I would appreciate any help I can get, I am still getting my feet wet in PHP and MySQL.

Thanks!
02-Dec-11 17:33
@Brian Esser If I understand you question correctly, Matt answered it earlier. He said to add




public function storeFormValues ( $params ) {

if ( get_magic_quotes_gpc() ) $params['content'] = stripslashes( $params['content'] );

// Store all the parameters
$this->__construct( $params );


in the Article class file (just the second line to the storeFormValues() method). I had a similar problem and that solved it.

[Edited by DOC on 02-Dec-11 17:34]
02-Dec-11 18:13
Thanks! I missed that earlier, worked like a charm!

Now to figure out categories...
06-Dec-11 02:01
@digiguy: No problem

--
Matt Doyle, Elated
07-Dec-11 01:13
@matt

So I figured out the problem with the 403 error (I messed up a few links), but I am still having a difficult time figuring out why my articles are not appearing in the homepage or archive. I checked my MySQL database and everything seems to be in there and they also appear in the listArticles page.

Thanks for any help!
11-Dec-11 17:00
@cjcarey: What are the URLs of the homepage and archive page, so I can take a look?

--
Matt Doyle, Elated
11-Dec-11 20:33
Actually I finally figured it out, I had been directing to the wrong page. It was a very obvious mistake that took way too long to figure out.

Thanks for the help everything is up and running now.
17-Dec-11 03:20
@cjcarey: No problem - glad you got it working

--
Matt Doyle, Elated
17-Dec-11 17:39
Hi, I followed your article this morning, and really enjoyed it. Everything was so well explained.

But I am having a problem now that I have finished it

Fatal error: Call to undefined function: date_default_timezone_set() in /usr/local/pem/vhosts/101568/webspace/httpdocs/CMS/config.php on line 3

I copied your code, but thats the error I get. In that line I have :

date_default_timezone_set( "Australia/Sydney" ); // http://www.php.net/manual/en/timezones.php

I have checked it off the phpmanual site and I have entered it correctly, but I get the error.

Thanks in advance for your help!


Also, I just commented out the date_default.. line in the config file, but then I get the following error:

Parse error: syntax error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in /usr/local/pem/vhosts/101568/webspace/httpdocs/CMS/classes/Article.php on line 15

Is it related? Or have I made a mistake somewhere else as well?

[Edited by MisssRAE on 17-Dec-11 17:47]
18-Dec-11 16:18
Hi, I figured it out. After some digging I discovered that both PHP4 and PHP5 for were enabled, and PHP4 was set to the default. But when you look at the initial summary page it says it is running PHP5. Thanks if anyone looked into this for me.
19-Dec-11 23:17
@MisssRAE: I was going to say that it's probably because you're running PHP4!

--
Matt Doyle, Elated
20-Dec-11 11:51
Hi there!

Great tutorial! I'm trying to learn the basics on php. Understood everything, but i think there is something missing! Text-areas on the backoffice don't allow html :/ how to add this component?

Tried to use some wysiwyg php scripts but none worked well!

If you can give me an hint, i would appreciate!
26-Dec-11 18:06
Can anyone point me in the direction of adding images to this?
28-Dec-11 13:55
I have just followed your marvelous tutorial and have got it working on my localhost mysql. Thank you so much for a beautifully concise and clear explanation of what is involved.

I would like to be able to schedule when my articles appear on the homepage.php and have them not appear there after a certain date (but remain in listArticles, archives.php and viewArticle.php).

I believe I need to add two more fields to the cms articles table: pubstart and pubend, which I should then get from the mysql cms database and use in the homepage.php to publish and unpublish the title in the homepage.php. Am I on the right track?

But I am not sure how to code this. Could you or any of the other forum participants advise me on how to do this?

Many thanks,
Shelley

[Edited by shelley3 on 28-Dec-11 14:01]

--
What will we do when the power goes out?
30-Dec-11 10:36
Hi,
Very nice tutorial matt. I'm trying to learn php. I thing about pagination the articles but for my is not so simple. Maybe helps of course if you have a moment time. Many thanks.
30-Dec-11 10:43
Great tutorial, just quickly browsed through and this is exactly what I am looking for; a simple CMS without any unnecessary clutter that is easy to style, etc.

I'm pretty new to PHP which is why I intend to follow every step in this tutorial to help me learn. Is there a way to post to separate pages from the backend without creating a separate CMS for each one? For example, on my webpage I would like to create a news page and then a separate page for gig dates, it would be more convenient to then be able to select which page to publish to, as opposed to having to login to separate backend pages.

How difficult would it be to do this? and could somebody point me in the right direction.

Thanks,
Adam
06-Jan-12 03:00
@Colucas: If by "don't allow html" you mean that the CMS sends HTML straight to the browser instead of HTML-encoding it, see:

http://www.elated.com/forums/topic/5114/#post21828

--
Matt Doyle, Elated
08-Jan-12 03:08
@odinsmasher: See http://www.elated.com/forums/topic/5114/#post20643

--
Matt Doyle, Elated
08-Jan-12 03:17
@shelley3: I can't code it for you, but yes, you are on exactly the right track! Create pubstart and pubend fields in the DB, and corresponding pubstart/pubend properties in the Article class, then modify the methods in the Article class to read/write these values from/to the DB. Then you can compare the 2 properties of the Article object against the value of time() to determine whether to display the article or not.

--
Matt Doyle, Elated
09-Jan-12 09:41
Thank you so much for your reply, Matt.

You have confirmed what I partially managed to figure out: i.e. that after adding the pubstart and pubend fields in the DB, their properties should be defined in the Article class. I am in the process of coding the methods to be able to time the display of an article. Not there yet, but I will post my results when I get it right (or whine and cry if I can't).

The role of defining a class (which I had not done before in php) became much clearer after pondering all this. I am really getting a good understanding of php/form/html pages/database interaction from examining all the files from your cms tutorial.

What a powerful package!

Many thanks again!
Shelley

--
What will we do when the power goes out?
11-Jan-12 16:27
@AdamBarry: Yes. Essentially, you'd just create an article "category" database field and corresponding property, and modify the article edit form to allow you to assign a category to the article (eg "news" or "gigs").

You'd also modify Article::getList() to allow you to pass in a category to filter by.

Then you could modify archive() in index.php to look for a "category" variable in the $_GET array, and pass the category inside the call to getList() to bring back just the articles in that category (news or gigs). archive() could then require either a news.php or gigs.php template, instead of archive.php.

You'd then view your news and gigs listing pages with:

/?action=archive&category=news
/?action=archive&category=gigs

Cheers,
Matt

--
Matt Doyle, Elated
11-Jan-12 18:24
@shelley3: You're welcome - I'm pleased you learned a lot from the tutorial.

--
Matt Doyle, Elated
12-Jan-12 12:15
How i can use UTF-8, for save & load news in mySQL?
:-/
12-Jan-12 22:03
@GLinBoy

just add


" array (PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8 "

after new PDO line.

ex.

$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD, array (PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8") );


[Edited by chotikarn on 12-Jan-12 22:28]
13-Jan-12 02:02
@chotikarn
thank you.
but i have a problem; I can find "$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );" in article class an replace with "$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD, array (PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8") );" but i got this error: Fatal error: Undefined class constant 'MYSQL_ATTR_INIT_COMMAND' in C:\wamp\www\classes\Article.php on line 103
:-?
I don't know that what happened!
something that i forget it is that i using WAMP 2.0 & PHP 5.3.0 & MySQL 5.1.36 run on windows 7 ultimate.

[Edited by GLinBoy on 13-Jan-12 02:09]
13-Jan-12 09:12
@GLinBoy
i use XAMPP 1.7.7 on Windows XP SP3 and it's work fine on me (i use thai language).

but,it has many way to use utf-8, i hope this one might work on you.

new PDO('dblib:host=your_hostname;dbname=your_db;charset=UTF-8', $user, $pass);

or else try normal way of "mysql_connect" instead of PDO.

if you need more information about PDO just visit php.net

PS.sorry for my bad english.

[Edited by chotikarn on 13-Jan-12 09:16]
13-Jan-12 10:04
Really great tutorial Matt! Congrats!

I've set my database and installed it, and went on the admin site on my webpage, wrote an article, but it didn't appear anywhere...
It says "0 written articles"

Did I miss something?
14-Jan-12 13:20
Hello Janjetina,

Have you named the fields in your database exactly the same as the fields specified in the Article.php, editArticle.php and other php documents?

(The names in this tutorial are "id, publicationDate, title, summary, content" and are case sensitive.)

Have you specified the field types in your database? Have you made "id" an auto-increment and the database index?

Have you specified the path to your DB_DSN in the config.php? (e.g. "mysql:host=localhost;dbname=your_db_name")

Is the timezone in the config.php set to your local time?

Are you getting any error messages like "failure to open . . . " , etc?


Shelley

--
What will we do when the power goes out?
14-Jan-12 14:16
Thank you Matt, for this tutorial! I certainly learned a lot from this and I managed to get it al working.

My next step is to try to add an image-upload, like m4xjb. I followed his steps and Matts comments and tips but I can't get it to work.

Do I have to implement the file handle (to actually 'get' the file from the form and place it in the right folder) in the __construct function? Or is it done some place else (in the insert function)?
16-Jan-12 03:50
@GLinBoy: Also this might help:

http://stackoverflow.com/questions/2424343/undefined-class-constant-mysql-attr-init-command-with-pdo

@b0bx: Just call move_uploaded_file() to move the uploaded image file to your desired folder. I would call it at the point where the article edit form submission is handled (e.g. in newArticle() and editArticle() in admin.php).

--
Matt Doyle, Elated
16-Jan-12 09:55
Thank You shelley3!

Now it works fine, I've made a few changes and thus forgot about those little details.

Now what if I want to add another property in the article, for example: in between the summary and content I want another content, let's say content2

Where and in which .php documents do I need to specify the new property and which lines of code do I need to add. (Beyond of course the ordinary label and id in editArticle.php and few lines in homepage.php) ?
16-Jan-12 15:04
Hello Janjentina,

I'm so glad this was helpful.

If you want to add more properties, you will have to add an additional field for that property into your database e.g.:
Field: content2
Type: mediumtext
Collation: utf8_swedish_ci
Null: No
Default: None

Then you will need to add that property into the cms/classes/Article.php under:

class Article
public function __construct( $data=array() )
public function insert()
public function update()

e.g. wherever


if ( isset( $data['content'] ) ) $this->content = $data['content'];

appears, add your new property



if ( isset( $data['content2'] ) ) $this->content2 = $data['content2'];

to the function (in Article.php)

For the form (in editArticle.php) you will need to add:


<li>
<label for="content2">Article Content2</label>
<textarea name="content2" id="content2" placeholder="The HTML content2 of the article" required maxlength="100000" style="height: 30em;"><?php echo htmlspecialchars( $results['article']->content2 )?></textarea>
</li>


In each case, make sure the property name, id, $this, $data have the correct name of "content2".

Best,
Shelley

--
What will we do when the power goes out?
18-Jan-12 06:28
Thanks Matt, you have been a great help.

Is there a way to tidy up the URLs to look like:

mysite.com/news
mysite.com/gigs

instead of

/?action=archive&category=news
/?action=archive&category=gigs

and also what properties would i need to add to the category field in the database table?

Thanks,
Adam

[Edited by AdamBarry on 18-Jan-12 06:51]
18-Jan-12 12:09
Hello shelley3
Thanks again for the response

However,

I get this error when writing the new article:

Notice: Undefined property: Article::$content2 in /home/users/pustolovac/klada.hr/cms/templates/admin/editArticle.php on line 30

but everything is fine on line 30. But the part I don't understand very well is what exactly to write in Article.php in this sections:

public function __construct( $data=array() )
public function insert()
public function update()

Do I always need to put this?

if ( isset( $data['content2'] ) ) $this->content2 = $data['content2'];
19-Jan-12 11:36
Hallo @matt,

This was great tutorial i liked the way you build your code and also the explanation.
It would be very useful to add comment page, if get the time for that.
Could you please explain what should be done, if some one want to add a comment page to the cms. i can imagine the comment page would have properties like this


public $id = null;
/*
* @var date , publication date
*/
public $publicationDate = null;

/*
* @var id , foreignkey. tells which article this comment belongs to
*/
public $articleId = null;
/*
* @var email, email
*/
public $email = null;
/*
* @var username, username
*/
public $userName = null;
/*
* @var content, content of the comment.
*/
public $content = null;


That is just my imagination when adding comment class to the our cms, i think the rest of the code would look like the one of the article class.
But i have got a question, should the class Comment be child class of the article some thing like

class Comment extends Article{}

if not, how would that be programmed. It would really be appreciated if you try @matt to explain it.
Thank you very much for your contribution.

[Edited by mubuuba on 19-Jan-12 11:38]
20-Jan-12 00:02
@AdamBarry: You'll be pleased to know that I'm writing a tutorial on adding categories to the CMS right now

Yes, you can tidy up the URLs (assuming you're running an Apache server and have appropriate permissions) by using mod_rewrite rules inside an .htaccess file in your document root. The rules map the "tidy" URLs to the URLs needed by the CMS. For example:


RewriteEngine On
RewriteRule ^news(/$|$) /?action=archive&category=news [L]
RewriteRule ^gigs(/$|$) /?action=archive&category=gigs [L]


--
Matt Doyle, Elated
20-Jan-12 00:09
@Janjetina: Did you add the $content2 property at the top of your Article.php file?

eg:


/**
* @var string (describe property here)
*/
public $content2 = null;


You'll need to find all instances of the $content property in Article.php, and copy and paste the code, replacing $content with $content2 in the copied code.

eg in Article::__construct(), you'd add:


if ( isset( $data['content2'] ) ) $this->content2 = $data['content2'];


In Article::insert(), you'd make these changes:


$sql = "INSERT INTO articles ( publicationDate, title, summary, content, content2 ) VALUES ( FROM_UNIXTIME(:publicationDate), :title, :summary, :content, :content2 )";
$st = $conn->prepare ( $sql );
$st->bindValue( ":publicationDate", $this->publicationDate, PDO::PARAM_INT );
$st->bindValue( ":title", $this->title, PDO::PARAM_STR );
$st->bindValue( ":summary", $this->summary, PDO::PARAM_STR );
$st->bindValue( ":content", $this->content, PDO::PARAM_STR );
$st->bindValue( ":content2", $this->content2, PDO::PARAM_STR );


etc...

--
Matt Doyle, Elated
20-Jan-12 00:32
@mubuuba: Your Comment class looks about right, but no, it shouldn't extend Article since it shares virtually no characteristics with the Article class.

Instead, make it a stand-alone class that maps to your comments table in the DB. You can then include Comment.php inside your Article.php class, and write methods like Article::getComments() that gets all the Comment objects for a given article, which you can then display. (Or you can create methods such as Comment::getAllForArticle( $article ) if you prefer to do it that way round.)

Make sure you use at least a captcha to reduce comment spam

I'm thinking about writing another tutorial showing how to add comments to the CMS. Out of interest, would you prefer a tutorial showing how to add comments directly in the CMS itself, or a tutorial that shows how to add comments using Facebook, Disqus etc? Which do you prefer?

--
Matt Doyle, Elated
20-Jan-12 04:24
@matt, You are really a good programmer and you do it neatly.
MAtt as you have seen and read i am not the only one who asked that question. It is almost a hot topic here. Your cms is cool and nice that is why people like it.
I am respecting your time constraints. But matt if you could add a comment class{} in this cms would be great, because people are learning skills from there too.
I have already tried to add comment class and i did but i think i am not doing it a neat way.
This cms is great work from you respect.
But if you add that comment class and as you said categories too, it would be just a complete cms news system.
I would like that you add it to this cms..

Again Thanks a lot.
20-Jan-12 06:37
Thanks for this tutorial! I have been looking for something like this for a while.

When I login to the admin page I receive the "Invalid Username and password" error. The username and password I use matches perfectly with the ones I entered on the config.php file.

I'm stuck. What can you suggest?

Thanks.
20-Jan-12 10:34
Hello mpierce1001,

Are you using your ADMIN_USERNAME and ADMIN_PASSWORD or your DB_USERNAME and DB_PASSWORD?

Are you using PHPMyAdmin to connect to the database?

How you set your usernames and passwords in mySQL and the permissions you established (e.g. root, localhost, guest, another_username); and, if you are using PHPMyAdmin, how you configured that (in the PHPMyAdmin config.php) to communicate with MySQL determines what username and password you need to use.

I use PHPMyAdmin and have configured my username and password in the cms configure.php document to access MySQL with that name and password (not my DB_USERNAME and DB_PASSWORD).

I don't have these documents in front of me, so I can't explain much more than this right now. But, if you are still having a problem, I can delve into this more tomorrow.

Best,
Shelley

--
What will we do when the power goes out?
20-Jan-12 22:08
I am using the ADMIN_USERNAME and the ADMIN_PASSWORD to login to the admin page, but it still gives me the "invalid username and password" error. I am using myPHPadmin through Fatcow web hosting. Please help I am at a loss.
21-Jan-12 12:21
Hi mpierce1001,

Are the ADMIN_NAME and ADMIN_PASSWORD in your cms config.php file the same as the database username and password that Fatcow.com assigned to you for MySQL?

If not, change your ADMIN_NAME and ADMIN_PASSWORD to be the same as your Fatcow-assigned username and password. And make sure your cms configure.php mysql:host=the Fatcow information for the database name, and that DB_USERNAME and DB_PASSWORD match the same Fatcow-assigned username and password.

So your cms configure.php DB_ and ADMIN_ information will be the same.

My web hosting company gave me these instructions for when I begin using their MySQL server:
"Please note that your MySQL password is different from your main account password (i.e. mail, ftp, ssh) . . ."

Hope this helps.

Best,
Shelley

--
What will we do when the power goes out?
21-Jan-12 16:56
Still no luck. All my username and password are accurate and so is the host name url. I'm so lost...it is probably something really easy but I am so confused.

Thank you so much for your help.
21-Jan-12 17:56
Hi mpierce1001,

Have you contacted Fatcow.com support? Since you are using the phpMyAdmin through them, they should be able to tell you what is not working.

php, mysql and phpMyAdmin are very complicated to set up.

Are you on a PC or a Mac? If so, what OS?

php has a php.ini that needs to be properly configured.

phpMyAdmin has a config.inc.php that has to be properly configured.

mysql also needs to be properly configured.

So it is definitely not a simple thing. I know you are not the only one having these difficulties.

--
What will we do when the power goes out?
21-Jan-12 19:43
still no luck Fat Cow's support isn't much help. Everything is set up properly I just don't get it.
21-Jan-12 23:48
Ok I'm pretty sure it is connecting to the database but for some reason the login function is not linking back to the data in the config.php....any ideas?
22-Jan-12 07:35
Ok I fixed the login thank you for your help!!!!

Now I am getting this error when trying to load my editArticle.php

Parse error: syntax error, unexpected ';' in /hermes/web07/b2556/moo.theveganviewpointcom/editArticle.php on line 37

I believe it is in relation to the use of tinyMCE to replace the textarea form.

This is the code in my header:

<script language="javascript" type="text/javascript" src="tiny_mce/tiny_mce.js"></script>
<script language="javascript" type="text/javascript">
tinyMCE.init({
theme : "advanced",
mode : "textareas"
});


This is the textareas code:

<li>
<label for="content">Article Content</label>
<textarea name="content" id="content" placeholder="The HTML content of the article" required maxlength="1000000"><?php echo htmlspecialchars( $results['articles']->content )?></textarea>
</li>
22-Jan-12 16:18
Woohoo! Glad you fixed the login problem. How did you solve it? Knowing that will help other folks who might have the same difficulty.

Regarding:
"Parse error: syntax error, unexpected ';' in /hermes/web07/b2556/moo.theveganviewpointcom/editArticle.php on line 37"

What is the code used in line 37? Looks like there is a semicolon ( ; ) that shouldn't be where it is.

--
What will we do when the power goes out?
22-Jan-12 17:05
I just deleted the database and re installed it changed the code to pull from the DB username and password and bam it worked...the code on line 37 is in my previous post relating to the 'content' textarea. There is no ; in the code Li.e...which is why I am confused
23-Jan-12 00:53
@mpierce1001: There is a ';' in your code, at the end.

Without seeing your whole editArticle.php and header.php files I can only make educated guesses, but it sounds like you haven't delimited your PHP code properly at some point (by using '<?php' to start PHP code and '?>' to end it).

--
Matt Doyle, Elated
23-Jan-12 01:44
Thank you for best tutorial, matt. i was learn a lot from it. i was adapt it and now i have my own CMS and it work like a charm.

Thank you.

--------
@mpierce1001 your code show that you don't have </script>. it's might be your problem.

i have use tinyMCE before but it ruin my template(maybe i misconfig it), then i use ckeditor and it work well.

note: to use WYSIWYG editor a textareas's attribute required must be removed.
25-Jan-12 05:50
I have installed CKEditor and it shows up. However, it swallows up everything on the page. How can I prevent that.

I still want to separate title, summary, content, and date fields so they can all be inputted separately for the database. CKEditor displays but with everything inside it's text editor including the logged in as and logout button and the submit button....help please and thank you
25-Jan-12 19:19
For all those who want to add article categories to their CMS, I've just posted a new tutorial that will help you out:

http://www.elated.com/articles/add-article-categories-to-your-cms/

@chotikarn: You're welcome

@mpierce1001: Not sure what you mean exactly. Can you post a screenshot somewhere? Sounds like you might have invalid markup, or else you need to configure CKEditor to only enhance your textarea.

--
Matt Doyle, Elated
25-Jan-12 19:36
@matt wow, i'm looking for it, thanks you matt. i just add my category to your CMS but this is greater than mine.

@mpierce1001 maybe you should config ckeditor for only one textarea in this case only content's textarea because i was config it like that and work fine.
and you should clean your script or tag(ensure that all tag was close) before use any WYSIWYG editor.
25-Jan-12 19:50
How do you configure ckeditor to just handle the textarea?

right now in my header I have:

<script type="text/javascript" src="ckeditor/ckeditor.js">
</script>

and then in the body:

<li>
<label for="content">Article Content</label>
<textarea name="content" id="content" placeholder="The HTML content of the article"><?php echo htmlspecialchars( $results['article']->content )?>
</textarea>
<script type="text/javascript">
CKEDITOR.replace('content');
</script>
</li>

and it shows up, but with everything else from the page inside the ckeditor text box.
25-Jan-12 21:14
First, off this tutorial is great. I am not new to php but new to a project that is this advanced. I tried to alter the code to work with a project I am trying to work on, in an attempt to learn more about php. I've added different fields and have edited all of the files. However, whenever I try to post a new article, it says changes have been saved, while my database remains untouched.

Edits to Article class (which I have changed to TechCard:


public $id = null;
public $emp_first_name = null;
public $emp_last_name = null;
public $emp_number = null;





public function __construct( $data=array() ) {
if ( isset( $data['id'] ) ) $this->id = (int) $data['id'];
if ( isset( $data['first'] ) ) $this->emp_first_name = $data['first'];
if ( isset( $data['last'] ) ) $this->emp_last_name = $data['last'];
if ( isset( $data['empNumber'] ) ) $this->emp_number = $data['empNumber'];
}




public function storeFormValues ( $params ) {
// Store all the parameters
$this->__construct( $params );
}



public function insert() {

if ( !is_null( $this->id ) ) trigger_error ( "TechCard::insert(): Attempt to insert a Tech Card object that already has its ID property set (to $this->id).", E_USER_ERROR );

$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "INSERT INTO serials ( first, last, empNumber ) VALUES (:first, :last, :empNumber )";
$st = $conn->prepare ( $sql );
$st->bindValue( ":first", $this->emp_first_name, PDO::PARAM_STR );
$st->bindValue( ":last", $this->emp_last_name, PDO::PARAM_STR );
$st->bindValue( ":empNumber", $this->emp_number, PDO::PARAM_STR );
$st->execute();
$this->id = $conn->lastInsertId();
$conn = null;
}


Other files have been updated accordingly. Like I said, I get no error and everything seems to be working fine. It's just when I add a new article nothing is added. I know I missed something somewhere.

[Edited by pacothelovetaco on 25-Jan-12 21:18]
26-Jan-12 02:16
@mpierce1001
here is my config.

<script type="text/javascript" src="js/ckeditor/ckeditor.js"></script>
<script type="text/javascript">
window.onload = function()
{
CKEDITOR.replace('content');
};
</script>


@pacothelovetac i got some problem like you before maybe check your

<input type="submit" name="saveChanges" value="Save" />

name attribute must same as

if (isset($_POST['saveItem']))

in admin.php for
PS. i'm new to php. in fact i'm a designer.
26-Jan-12 03:05
@chotikarn I double checked and they do match.

I have:

<input type="submit" name="saveChanges" value="Save Changes" />


and in admin.php:

if ( isset( $_POST['saveChanges'] ) ) {
...
}


Thank you for the suggestion. That's one variable checked.
26-Jan-12 07:00
Thanks for your help, but I cannot fix it.

I am getting frustrated as no matter what I do to try and seperate the form elements everything populates inside ckeditor.

Even the page title the logged in as everything within the content area of the page populates inside the ckeditor.

Help please.
26-Jan-12 12:53
Hy there !

I have a BIG problem here... :'(
I've downloaded the zip (did make the sql part too) then rewrote the codes from here. (ctrl+c-->ctrl+v)

Then I got a Fatal error :

"Fatal error: Class 'PDO' not found in D:\cms\classes\Article.php on line 104"

So what could be the problem here ?

We already have a code that contains PDO on line 84 if I'm right.
So why the problem is on line 104 if we have the exact same code on line 84 ?

PLS HELP !!
26-Jan-12 21:59
I was able to fix my issue.

It turns out that


$sql = "INSERT INTO serials ( first, last, empNumber ) VALUES (:first, :last, :empNumber )";


Actually should be


$sql = "INSERT INTO serials ( emp_first_name, emp_last_name, emp_number ) VALUES (:first, :last, :empNumber )";


Now it's saving data in the database. But now, I cannot retrieve the data. For instance, in listArticle.php I have:

<?php foreach ( $results['techCards'] as $techCard ) { ?>

<tr onclick="location='admin.php?action=editTechCard&amp;techCardId=<?php echo $techCard->id?>'">
<td>
<?php echo $techCard->emp_last_name ?>, <?php echo $techCard->emp_first_name ?>
</td>
</tr>

<?php } ?>


It finds the ID just fine, but won't print any other data from the database. Am I trying to retrieve the data right?
26-Jan-12 22:12
@krisee99 If I'm not mistaken, the PDO on line 84 is part of a function that gets called depending on what your are trying to do (ie edit the article). But creating a new article doesn't call that function, it calls the function with PDO on line 104.

You need to see if you have PDO enabled in your php.ini file.
27-Jan-12 00:38
@pacothelovetaco: I'd recommend using the same field names throughout your script, templates and MySQL table to avoid confusion and potential problems.

eg if your MySQL field is called emp_first_name then make sure your TechCard property is also called $emp_first_name, and that your form field is <input name="emp_first_name" ...>.

The code you've posted so far looks OK, so I'm guessing there's a problem in your class whereby your TechCard objects aren't getting populated properly. At a guess, it's because your __construct() method is expecting different $data array keys to the table field names (first, last, empNumber instead of emp_first_name, emp_last_name, emp_number).

So again - make sure you use the same field names throughout your whole CMS!

--
Matt Doyle, Elated
27-Jan-12 00:41
@mpierce1001: It does sound as if you have invalid markup in your form page, which is confusing CKEditor. Can you view your form page's source in your browser, then copy and paste the source here? (Use the <> button to wrap 'code' markers around the code for readability.)

Also have you tried running the page source through http://validator.w3.org/ ?

--
Matt Doyle, Elated
27-Jan-12 05:38
Thanks Matt!

It was a markup confusion. The problem was that my <div> containing all the page elements had the same name as the <textarea> I was trying to replace. So CKEditor was just replacing the <div>, thus placing all elements within that <div> inside it's text box. I changed the name of the <div> and it worked perfectly! Now I'm on to another debugging process. Won't retrieve my articles continues to display 0 articles. And I tested the CKEditor and it saves the data into my database just fine; its just not pulling it and displaying it anywhere in the site.

Thanks again everyone for your help.
27-Jan-12 07:00
@pacothelovetac Ty for your answer, I'm a newbie here.
If I'm right i have it enabled but in case if not how do I check that I have PDO enabled in my php.ini ?

Do i need to have ";" this before the extension or not?
27-Jan-12 07:49
@krisee99 delete ; to enable.

you can use phpinfo() to check your PHP detail.
27-Jan-12 10:23
Hi and congratulations for your great article that led me to my first self-made CMS.

Anyway, I'm facing an issue and you could help me.

Everything is working fine both in frontend and backend, storing and retrieving articles, except for the 'listArticles' view.

In that, the server displays "Invalid argument supplied for foreach()" referring to the:

foreach ( $results['articles'] as $article )

as values are not in array...

I merged your tips with my login system (I excluded your login/logout infrastructure), but I don't think this is the problem...in fact, everything is ok a part of this.

Thanks a lot for the help you can provide me.
28-Jan-12 08:16
Please help!

I cannot get any articles to be retrieved anywhere on the site.

Everywhere just says "0 Articles" or there is nothing displayed at all.

I have checked everything and it all seems to match consistently with the articles table.

Is there something that needs to be set-up with MySQL to allow the PHP code to retrieve the articles?

Thanks in advance for any help.

<code>
<?php
/**
* Class to handle articles
*/

class Article
{

// Properties

/**
* @var int The article ID from the database
*/
public $id = null;

/**
* @var int When the article was published
*/
public $publicationDate = null;

/**
* @var string Full title of the article
*/
public $title = null;

/**
* @var string A short summary of the article
*/
public $summary = null;

/**
* @var string The HTML content of the article
*/
public $content = null;


/**
* Sets the object's properties using the values in the supplied array
*
* @param assoc The property values
*/

public function __construct( $data=array() ) {
if ( isset( $data['id'] ) ) $this->id = (int) $data['id'];
if ( isset( $data['publicationDate'] ) ) $this->publicationDate = (int) $data['publicationDate'];
if ( isset( $data['title'] ) ) $this->title = preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['title'] );
if ( isset( $data['summary'] ) ) $this->summary = preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['summary'] );
if ( isset( $data['content'] ) ) $this->content = $data['content'];
}


/**
* Sets the object's properties using the edit form post values in the supplied array
*
* @param assoc The form post values
*/

public function storeFormValues ( $params ) {

//Store all the parameters
$this->__construct( $params ) ;

// Parse and store the publication date
if ( isset($params['publicationDate']) ) {
$publicationDate = explode ( '-', $params['publicationDate'] );

if ( count($publicationDate) == 3 ) {
list ( $y, $m, $d ) = $publicationDate;
$this->publicationDate = mktime ( 0, 0, 0, $m, $d, $y );
}
}
}


/**
* Returns an Article object matching the given article ID
*
* @param int The article ID
* @return Article|false The article object, or false if the record was not found or there was a problem
*/

public static function getByid( $id ) {
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "SELECT *, UNIX_TIMESTAMP(publicationDate) AS publicationDate FROM articles WHERE id = :id";
$st = $conn->prepare( $sql );
$st->bindValue( ":id", $id, PDO::PARAM_INT );
$st->execute();
$row = $st->fetch();
$conn = null;
if ( $row ) return new Article( $row );
}


/**
* Returns all (or a range of) Article objects in the DB
*
* @param int Optional The number of rows to return (default=all)
* @param string Optional column by which to order the articles (default="publicationDate DESC")
* @return Array|false A two-element array : results => array, a list of Article objects; totalRows => Total number of articles
*/

public static function getList( $numRows=1000000, $order="publicationDate DESC" ) {
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "SELECT SQL_CALC_FOUND_ROWS *, UNIX_TIMESTAMP(publicationDate) AS publicationDate FROM articles
ORDER BY " .mysql_escape_string($order) . "LIMIT :numRows";

$st = $conn->prepare( $sql );
$st->bindValue( ":numRows", $numRows, PDO::PARAM_INT );
$st->execute();
$list = array();

while ( $row = $st->fetch() ) {
$article = new Article( $row );
$list[] = $article;
}

// Now get the total number of articles that matched the criteria
$sql = "SELECT FOUND_ROWS() AS totalRows";
$totalRows = $conn->query( $sql )->fetch();
$conn = null;
return ( array ( "results" => $list, "totalRows" => $totalRows[0] ) );
}


/**
* Inserts the current Article object into the database, and sets its ID property.
*/

public function insert() {

// Does the Article object already have an ID?
if ( !is_null( $this->id ) ) trigger_error ( "Article::insert(): Attempt to insert an Article object that already has its ID property set (to $this->id).", E_USER_ERROR );

// Insert the Article
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "INSERT INTO articles ( publicationDate, title, summary, content ) VALUES ( FROM_UNIXTIME(:publicationDate), :title, :summary, :content )";
$st = $conn->prepare ( $sql );
$st->bindValue( ":publicationDate", $this->publicationDate, PDO::PARAM_INT );
$st->bindValue( ":title", $this->title, PDO::PARAM_STR );
$st->bindValue( ":summary", $this->summary, PDO::PARAM_STR);
$st->bindValue( ":content", $this->content, PDO::PARAM_STR);
$st->execute();
$this->id = $conn->lastInsertId();
$conn = null;
}


/**
* Updates the current Article object in the database.
*/

public function update() {

// Does the Article object have an ID?
if ( is_null( $this->id ) ) trigger_error ( "Article::update(): Attempt to update an Article object that does not have its ID property set.", E_USER_ERROR );

// Update the Article
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "UPDATE articles SET publicationDate=FROM_UNIXTIME(:publicationDate), title=:title, summary=:summary, content=:content WHERE id = :id";
$st = $conn->prepare ( $sql );
$st->bindValue( ":publicationDate", $this->publicationDate, PDO::PARAM_INT );
$st->bindValue( ":title", $this->title, PDO::PARAM_STR );
$st->bindValue( ":summary", $this->summary, PDO::PARAM_STR );
$st->bindValue( ":content", $this->content, PDO::PARAM_STR );
$st->bindValue( ":id", $this->id, PDO::PARAM_INT );
$st->execute();
$conn = null;
}


/**
* Deletes the current Article object from the database.
*/

public function delete() {

// Does the Article object have an ID?
if ( is_null( $this->id ) ) trigger_error ( "Article::delete(): Attempt to delete an Article object that does not have its ID property set.", E_USER_ERROR );

// Delete the Article
$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$st = $conn->prepare ( "DELETE FROM articles WHERE id = :id LIMIT 1" );
$st->bindValue( ":id", $this->id, PDO::PARAM_INT );
$st->execute();
$conn = null;
}

}
?>
</code>
28-Jan-12 08:26
Hi,
I solved my previous issue.
I was wrongly calling listArticles.php and editArticle.php by themselves instead of calling admin.php.

Now everything is perfect except for a double quote escape problem.

When I store articles' content in database, double quotes are wrongly escaped as for example:

<img src="\"http://www.musicclub.it/foto/es/big/ESCAPE_THE_FATE.png.big.jpg\"" width="\"250\"/">


Any hint? PDO mysql calls by bindValue() seem correct...
28-Jan-12 09:50
@asnothingelse

i had problem like you before...
my article had many \\\\\ so i use below code to fix it.

ini_set ("magic_quotes_gpc", false);

add it in config.php to disable magic quote for some host that was enable it.
i think it might work.

@mpierce1001

your code pain my eyes
is it only show "0 article" or none of them showed.

see here


// Now get the total number of articles that matched the criteria
$sql = "SELECT FOUND_ROWS() AS totalRows";
$totalRows = $conn->query( $sql )->fetch();
$conn = null;
return ( array ( "results" => $list, "totalRows" => $totalRows[0] ) );
}


and look in your index.php (or handle function page) for


$results['totalRows'] = $data['totalRows'];


then check on your include page (archive.php) to ensure that it was echo $results['totalRows'].

if it not show any article it maybe other problem.

PS.let's me know if it not work, i'm just share my opinion for some case that i was face before.
28-Jan-12 10:03
@chotikarn

Thanks for the tip I checked all of that again that you suggested and everything matches. I have checked and checked again all the code that retrieves data and I cannot find any errors.

Any ideas on what else it could be?

Are there settings in the php.ini that need to be configure or settings in the MySQL that need configured?

Thanks for all your help!
28-Jan-12 10:05
@chotikarn

thanks for you hint, but I surprisingly solved my escaping trouble!

I discovered that if I avoid double quotes in the article editor, when I write HTML, the CMS will add by itself without any other errors.

If I write this in the backend editor:

<img src=http://.... alt=Alternative id=img/>


..then I obtai this in fronted:

<img src="http://...." alt="Alternative" id="img"/>


which is right!
Maybe, this could be brought by the magic quotes of the server setting (I didn't know about it).
If I'd disable it, like you suggest, probably I could normally write in the editor with double quotes too.

I will try !

[Edited by asnothingelse on 28-Jan-12 10:06]
28-Jan-12 11:01
@mpierce1001

maybe PDO drive does not enable to connect or MySQL
use try - catch to handle PDO connection
this code might help your to check PDO connect to MySQL



<?php
try {
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
foreach($dbh->query('SELECT * from FOO') as $row) {
print_r($row);
}
$dbh = null;
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
?>

in other way try to use Xdebug it's help a lot to find error.

Note: Xdebug was include with XAMPP just enable it in php.ini.

@asnothingelse

i'm new to php (but not HTML and CSS) then i feel surprise too.
my given solution might not match your problem, but it worthy to try.

look at php.net for more detail, it was help me a lot.

[Edited by chotikarn on 28-Jan-12 11:03]
28-Jan-12 22:03
Hi guys

I m new to php and this is an awesome tutorial to a real world php app.
Thank you mat for doing this thx alot

I hv a question it may be silly still.

I cnt actually figure out where is the main object of the class Ariticle were made.. cant find a like



$myobj=new Article();


outside the class file in any other files.

If anyone can help me understand this that will be very helpful
Thank You

[Edited by avisek on 28-Jan-12 22:06]
30-Jan-12 01:03
@avisek: Article objects are created in 3 places:

In admin.php (inside newArticle())
In Article.php (inside getById() and getList())

Look for the code "new Article".

Cheers,
Matt

--
Matt Doyle, Elated
30-Jan-12 12:41
@Matt eww thx i got it now
was a silly question

thx a lot for the tutorial
09-Feb-12 09:48
This article was amazing! Thank you Matt for your superb work.
Well written and good to learn from!
I'm kind of new to this whole php-thing, but I'm learning from every tutorial

I have, at this date, included a whole custom CSS, the CKEditor and KCFinder to this work, just to play with, and it works great (after several face-palms and whatnots)!

For thos who are interested, a sample: Guolldo dot com/cms/admin dot php

Now, my next task is to integrate a pagination, and here is where I'm stuck. I have tried to search the web for a good tutorial that I can combine whit the whole cms, but every tut I read ends up with me looking like a question mark.

So..
Can somebody maybe point me in the right direction for some good documentation?

Or, Matt. Have you taught about maybe write a follow-up article with pagination? I think there are many of us that would be able to learn allot more, and discover new possibilities whit one more good tutorial

Thanks allot again, and I apologize for my spelling and grammar.. / J
09-Feb-12 11:36
@jj if you would like to add pagination, try this...

first make new function in Class


public static function getPaginate( $order="publicationDate DESC" ) {

$per_page = 7; //set item per page

$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD, array (PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8") );
$sql = "SELECT * FROM articles";
$query = $conn->query( $sql )->fetchAll();
$Num_Rows = count($query);

if(empty($_GET['page']) ){
$_GET['p'] = "";
}
$p= $_GET['page'];
if(!$_GET['page']) {
$page =1;
}
$Prev_Page = $page-1;
$Next_Page = $page+1;

$Page_Start = (($per_page*$page)-$per_page);
if($Num_Rows <= $per_page)
{
$Num_Pages = 1;
}
else if (($Num_Rows % $per_page) == 0)
{
$Num_Pages = ($Num_Rows/$per_page);
}
else
{
$Num_Pages =($Num_Rows/$per_page)+1;
$Num_Pages = (int)$Num_Pages;
}

$query = "SELECT SQL_CALC_FOUND_ROWS *, UNIX_TIMESTAMP(publicationDate) AS publicationDate FROM articles
ORDER BY " . mysql_escape_string($order) . " LIMIT $Page_Start, $per_page";
$result = $conn->prepare($query);
$result->execute();
$list = array();

while ($row = $result->fetch() ) {
$article = new Articles( $row );
$list[] = $article;
}

$conn = null;
return ( array ( "results" => $list, "Num_Rows" =>$Num_Rows, "Num_Pages" => $Num_Pages, "page" => $page, "Prev_Page" => $Prev_Page, "Next_Page" => $Next_Page ) );
}

and then modify our index.php to handle pagination function
i'm need to use it only in archive page, so here is it.


function archive() {

$results = array();
$data = Articles::getPaginate(); // call paging function instead of getById.
$results['articles'] = $data['results'];
$results['Num_Rows'] = $data['Num_Rows'];
$results['Num_Pages'] = $data['Num_Pages'];
$results['Prev_Page'] = $data['Prev_Page'];
$results['Next_Page'] = $data['Next_Page'];
$results['page'] = $data['page'];
$results['pageTitle'] = "Article Archive";
require( TEMPLATE_PATH . "/archive.php" );
}

then on the archive page we will render our pagination
just put it on top of archive list of bottom.


<div id="paginav">
<?php
$Current_Page = $_SERVER['SCRIPT_NAME'];
$Prev_Page =$results['Prev_Page'];
$Next_Page =$results['Next_Page'];
$Num_Pages =$results['Num_Pages'];
$page =$results['page'];
if($Prev_Page)
{
echo "<a href = '$Current_Page?action=archive&p=$Prev_Page'><< Previous</a>";
}
for($i=1; $i<=$Num_Pages; $i++){
if($i !=$page)
{
echo "<a href ='$Current_Page?action=archive&page=$i'>$i</a>";
} else {
echo "<span>$i</span>";
}
}
if($p != $Num_Pages)
{
echo "<a href ='$Current_Page?action=archive&page=$Next_Page'>Next>></a>";
}
?>
</div>


it's not look smooth enough but maybe helpful, and i'm newbie to PHP like you, cheer!.

Note, i have modified original code. maybe have conflict with original code, then let's me know, if it have any error.

[Edited by chotikarn on 09-Feb-12 11:42]
09-Feb-12 12:13
I wonder should I give that pagination code a try....or wait for Matt's approval It's pretty much the only thing keeping from putting my site live.
10-Feb-12 21:56
G'day Matt.

Absolutely brilliant tutorial on the CMS. It has helped bucketloads in a current project and has allowed me to completely avoid having to use Wordpress, Drupal etc.

I am experiencing a problem however. I can add an article, the id, summary and content are stored sucessfully in the DB. However, when I log in as admin, I get a "Notice: Trying to get property of non-object" error that seems to stem from the "editArticle.php" script.

I haven't edited your code in any way, however - it seems that the article object either hasn't been created (which I don't think is the case, as the data is correctly sent to the DB), or there is a block somehwere in accessing the object.

The error repeats on each input line of the form (id, title, summary, content and date) and in the relevant fields where one should be editing, it is spitting out the error tables in HTML format.

I am completely confuzzled, any help would be greatly appreciated.


Any help would be greatly appreciated!
11-Feb-12 05:42
@Matt

I found this webpage/post by accident and I am so glad I did. I have been a coding basic websites and apps for years, but I have always been worried about the security of my code (its pretty unsecure!).

I am going to re-write a few things around this model. I would love to see more tutorials like this one. I took the time to understand how it all works, rather than just download the zip files.

Thanks for this tutorial - I look forward to hitting the forums with any questions I may have!
11-Feb-12 18:28
Ok, so I think I found out what my problem is. I didn't have PDO enabled in my local php.ini. This isn't a problem, however - when I uploaded the project to my web host - they also did not have PDO enabled; when questioned if they could enable it for me, they advised that they were not able to due to due to other clients using Curl with SSL support.

So, my new question is this: what can I use in place of PDO? Would a basic DB class suffice? (Obviously losing some of the security that PDO gave). If so, how would that be implemented?
13-Feb-12 10:28
Hello...!

Thanks for the tutorial, its working pretty well here...! I am very thankfull for this...!

Its reading the db, showing all options...!

Then, i made some workarounds that not are running...!

I made a little tip window with JQuery which works with the content of articles...!

I put the scripts in header.php:

<script type='text/javascript' src='http://code.jquery.com/jquery-1.6.js'></script>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="script.js"></script>

all files inside "include" directory...!

When i call cms/index.php in browser all the page source code is the same of original working "index.html"...! But its not showing any effects...! All db/content are below my background image and the footer.php is in the top of page...! The db/content should be over background image with JQuery/CSS effect and footer.php on footer (obviously)...!

How could i include JQuery/CSS effects...?

Thank you.
14-Feb-12 01:55
@Marki maybe wrong path, check your path use debug console on chrome or firebug

belong to your code, it seem to find your file in cms folder.
so try..

src="/include/xxx.js"

[Edited by chotikarn on 14-Feb-12 01:58]
15-Feb-12 03:02
@chotikarn: Thanks for posting your pagination code

@DOC: Looks OK to me though I haven't tested it. I would do it slightly differently by using getList() but the basic idea looks sound.

@jj @DOC: I'm certainly planning a follow-up article on pagination. Just to be clear: When you guys say "pagination", do you want pagination of the homepage and archive page (anywhere that lists articles basically), or the ability to split actual articles into separate pages? I'm guessing the former rather than the latter?

Cheers,
Matt

--
Matt Doyle, Elated
15-Feb-12 04:48
@Matt Ya I had the pagination of article listings in mind but I guess I can't speak for everyone. I remember coming across a little jQuery sample that does the latter.

Thanks again.
15-Feb-12 05:29
chotikarn:

Thanks for reply, you solved my little prob...! It was the path of files...!

TY.
15-Feb-12 07:59
@Marki

i'm glad to hear that your problem was gone.

@Matt

i sound good to me to see "split actual articles into separate pages".

Thank you again.
17-Feb-12 02:53
@oxygen: Thanks for the feedback - I'm glad you found the tutorial helpful. Good luck with your sites

--
Matt Doyle, Elated
17-Feb-12 02:57
@BlackhawkNZL: Hmm, that's strange. PDO is pretty standard these days.

You could try MDB2, which is sort of a PEAR counterpart of PDO:

http://pear.php.net/package/MDB2

http://www.procata.com/blog/archives/2006/12/26/pdo-versus-mdb2/

It's all pretty similar stuff really - connect to the database, prepare an SQL statement, execute it, then fetch the result rows.

--
Matt Doyle, Elated
17-Feb-12 03:10
@DOC @chotikarn: OK, it sounds like you want both list page pagination and article page pagination! I'll see what I can do. I'll probably do list page pagination first as I suspect that's more in demand...

--
Matt Doyle, Elated
17-Feb-12 03:26
it's sound great, i can't wait for it!
17-Feb-12 21:02
Any idea why an article's publication date would decrease by a day every time the Edit Article form is saved? This didn't happen with the initial tutorial files, but it started happening after I added a few fields to the database and corresponding code. I've checked all the files a dozen times. I haven't changed anything pertaining to the publicationDate at all.

I got everything working except for the stupid date.
20-Feb-12 03:39
@SpitZu: Off the top of my head, that sounds like a timezone mismatch between PHP and MySQL. Check that the date_default_timezone_set() call in your config.php is setting the PHP timezone to your server's timezone. If it's correct, check MySQL.

--
Matt Doyle, Elated
21-Feb-12 10:43
Hi there, again, this is a great tutorial, got my CMS running nicely on my band's website, http://www.demob-happy.com/

I do have one issue that one user kindly pointed out to me. He mentioned that I was not capturing exception errors in my article class which in turn outputted the connection string along with the database username and password details like so:


Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000] [1203] User USER already has more than 'maxuser_connections' active connections' in /blahblah/blahblah/web/lalala/blahblah/news/classes/article.php:104 Stack trace: #0 /blahblah/blahblah/web/lalala/blahblah/news/classes/article.php(104): PDO->_construct('mysql:host=localhost', 'user', 'password') #1 ............


My site is working fine and this was the first that I had heard of this error, maybe the database was under heavy load opening and closing connections? So I then changed the article class to use persistant connections. The user who pointed this out then sent me a link to the php.net page on PDO connections.

http://php.net/manual/en/pdo.connections.php

Which mentions...

"If your application does not catch the exception thrown from the PDO constructor, the default action taken by the zend engine is to terminate the script and display a back trace. This back trace will likely reveal the full database connection details, including the username and password. It is your responsibility to catch this exception, either explicitly (via a catch statement) or implicitly via set_exception_handler()."

So how would I implement this in the public static functions that grab the articles from the database??
22-Feb-12 06:23
Hi Matt and all other people discussing here on this amazing tutorial!

I have few questions once again..

1. What do I need to rewrite in the code and where if I want my articles to be sorted by the time and date they are written, but that the newest appears on top, instead on the bottom as it is now

2. What do I need to change if I want more than 5 articles to appear on the page

3. Is it somehow possible that I have one row in which I can upload a simple photo in the article. Let's say that I have two photos -> photo1.png and photo2.png
So i would like, depending on the article, to have the possibility to choose which photo to put somewhere in the article

Thanks!

[Edited by Janjetina on 22-Feb-12 06:25]
22-Feb-12 08:38
@Janjetina

1. if you need to sort your aticles with time newest to oldest.
first, you need to change your "publicationDate" column in "articles" table to "Timestamp" and default must be "current_timestamp".
second, deleted whole <li>..Date.. </li> in editarticle
[ edit - i mean change type from "Date" to "Timestamp"]
now your CMS will order articles by time and date.

2. figure out in config.php find

define( "HOMEPAGE_NUM_ARTICLES", 5 );

now the number on your desire.

3. you can done that by use Ckeditor and Ckfinder. i have been done it before work like a charm.

[Edited by chotikarn on 22-Feb-12 08:49]
22-Feb-12 09:28
Big thanks chotikarn

I will post back when I'm done and when it will work, but from my position right now, can you please refer me to somewhat more instructions regarding my third question about pictures and the answers You have given to me
22-Feb-12 10:20
@Janjetina

as your pleasure... this will add your both Cover image for your article and can add picture to your article content

first of all you need

Ckeditor and Ckfineder(it's demo but fully function)

google will help you find it.

Then, put your Ckeditor and Ckfinder folder to your root dir and open your editarticle.php
in your <head> tag add


<script type="text/javascript" src="js/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="ckfinder/ckfinder.js"></script>

and


<script type="text/javascript">
window.onload = function()
{
CKEDITOR.replace('content',
{
filebrowserBrowseUrl : '/ckfinder/ckfinder.html',
filebrowserImageBrowseUrl : '/ckfinder/ckfinder.html?Type=Images',
filebrowserFlashBrowseUrl : '/ckfinder/ckfinder.html?Type=Flash',
filebrowserUploadUrl : '/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files',
filebrowserImageUploadUrl : '/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Images',
filebrowserFlashUploadUrl : '/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Flash'
});
};
</script>


that is simple setup for Ckeditor and Ckfinder
now go to your form add this code before form


<script type="text/javascript">

function BrowseServer()
{

var finder = new CKFinder();
finder.basePath = '/ckfinder/';
finder.selectActionFunction = SetFileField;
finder.popup();
}

function SetFileField( coverimage )
{
document.getElementById( 'coverimage' ).value = coverimage;
}

</script>



and add id="content" in <textarea name="content" /*add here*/></textarea>

and add new input element


<li>
<label for ="coverimage">Cover Image:</label>
<input id="coverimage" class="edit" name ="coverimage" type="text" value="<?php echo ( $results['article']->coverimage )?>"/>
<input type="button" style=" margin-left: 10px; padding: 5px;" value="Browse Image" onclick="BrowseServer();" />
</li>



------------------------
now we will move to work with Class file open it

and add


public $coverimage = null; // around top most to define our var

//and skip to construct function add

if ( isset( $data['coverimage'] ) ) $this->coverimage = $data['coverimage'];

//then go to insert function and modify $sql line
$sql = "INSERT INTO articles ( publicationDate, title, summary, content, category, coverimage ) VALUES ( FROM_UNIXTIME(:publicationDate), :title, :summary, :content, :category, :coverimage )";

//and add

$st->bindValue( ":coverimage", $this->coverimage, PDO::PARAM_STR );
// before
$st->execute();

//last do similar to update function but just add

coverimage=:coverimage into $sql line (before WHERE)


now we're almost done

go to your database and add new column
coverimage VARCHAR 255 not null

it might work now.

to add image in your article just add by use button in Text Editor
and click "brows serve" to upload and select

to add cover just click "Brows Sever" and file path will store in to your database

----------------------

move to front-end , index.php

in foreach add


<div id="a-cover"><img src="<?php echo $article->coverimage ?>" alt="cover image"></div>


now you have both Cover image and image in articles content.

PS. let's me know if you confuse or have any problem

[Edit - only spell check]

[Edited by chotikarn on 22-Feb-12 10:25]
22-Feb-12 11:10
Dear chotikarn, before I check this with photos, can please be more precise about my first question, sorting newest to oldest..
Can You please specify what changes need to be made and exactly where because I'm not able to make them work right now
22-Feb-12 12:30
Wow chotikarn!
This was an amazing tutorial for images, it works!!
Now i just need to fix this sorting by time...
22-Feb-12 20:24
@Janjetina

i'm sorry for unclear suggestion.

you need to go to your database by use something like "phpmyadmin", then select your database (which have "articles" table in side).
now, on "articles" table and click on "structure" and then look for "publicationDate" field/column, click "Change"

in new window change Type: to TIMESTAMP and default to "CURRENT_TIMESTAMP".

ok, now it's quite clear, right? and i'm very glad to hear that your image work fine.

ps. sorry for my bad english.
23-Feb-12 03:27
Now it's clear, I've done it but it doesn't work....
maybe i need to change something in my .php files?

You've mentioned doing something in the editArticle.php


<li>
<label for="publicationDate" >Date</label>
<input type="date" name="publicationDate" id="publicationDate" placeholder="YYYY-MM-DD" required maxlength="10" value="<?php echo $results['article']->publicationDate ? date( "Y-m-d", $results['article']->publicationDate ) : "" ?>" />
</li>



[Edited by Janjetina on 23-Feb-12 04:27]
23-Feb-12 06:28
@Janjetina

just delete those code, we do not use it anymore because we use MySQL to automatic insert current date and time instead of fill it manually.

[Edited by chotikarn on 23-Feb-12 06:30]
23-Feb-12 11:15
Works great!


Many thanks!
25-Feb-12 08:17
Hello, I had a bit of a problem implementing characters like öåä. So I used strtr like so.


$trans = array("^" => "", "," => "", "." => "", "_" => "", "'" => "", "\"" => "", "@" => "", "?" => "", "!" => "");
$this->title = strtr( $data['title'], $trans )


Would this be suggested, or should I be using preg_replace?

Also I would like to ask you if your thinking about doing the image upload tutorial anytime soon, if your going to do it.

Been messing around a bit with it this last weak but im having a real problem understanding the things going on in article.php.

I already have the image upload function written, it creates the thumbs and all that. Im just having a problem implementing it with the CMS!
27-Feb-12 21:05
@AdamBarry: Oops, good catch! (Pun not intended.)

The easiest workaround would be to add this to your index.php, just below the config.php require:


function handleException( $exception ) {
echo "Sorry, a problem occurred. Please try later.";
}

set_exception_handler( 'handleException' );


That will handle all exceptions, including any returned by PDO, and display a generic error message instead. Not the most elegant solution, but it will prevent the problem you describe.

The more elegant, though long-winded solution would be to add try...catch blocks to every PDO call within Article.php.

I'll update the tutorial.

Cheers,
Matt

--
Matt Doyle, Elated
27-Feb-12 22:24
@srtu: Try this for a utf-8 version of strtr():

http://stackoverflow.com/questions/1454401/how-do-i-do-a-strtr-on-utf-8-in-php

Will hopefully write the image upload tutorial some time soon (can't say when!).

--
Matt Doyle, Elated
28-Feb-12 10:23
Well i have accomplished to show a "Categories Menu" by doing this:

<?php
include 'config2.php';
$query = "SELECT id, name FROM categories";
$result = mysql_query($query);
$numrows = mysql_num_rows($result);
while($row = mysql_fetch_array($result))
{
echo "<li><a href=.?action=archive&amp;categoryId=$row[id]>$row[name]</a></li>";
}
?>

I Hope this helps somebody.

Amazing Tutorial really

Just so you know, the Config2.php contains the code to connect to the database.
28-Feb-12 13:57
Great tutorial. Still working from your source, and implementing some changes given by other readers.

q1: in phpinfo of my webhost I search for magic and get:
magic_quotes_gpc On On
magic_quotes_runtime Off Off
magic_quotes_sybase Off
first state is local value, second being master value.

The wording is confusing me, I assume I am safe and magic quotes is off

q2: Anyone want to share how they implemented hashing?

And for those who are wanting to integrate comments, I personally, prefer just to use an external service, like disqus. Integrating there system is easy and safe. Just add the code to viewArticle.php

Thank you again for a great resource.
28-Feb-12 18:58
managed to work out hashing:

My admin.php function login is as follows:


function login() {

[b]$salt = "Salt can be whatever you want to put here.";[/b]
$results = array();
$results['pageTitle'] = "Admin Login | somewebsitetitle";

if ( isset( $_POST['login'] ) ) {

// User has posted the login form: attempt to log the user in

if[b] ( hash('sha512', $salt . $_POST['username'])[/b] == ADMIN_USERHASH &&[b] hash('sha512', $salt . $_POST['password'])[/b] == ADMIN_PASSWORD ) {
// Login successful: Create a session and redirect to the admin homepage
$_SESSION['username'] = ADMIN_USERNAME;
header( "Location: admin.php" );

} else {

// Login failed: display an error message to the user
$results['errorMessage'] = "Incorrect username or password. Please try again.";
require( TEMPLATE_PATH . "/admin/loginForm.php" );
}

} else {


// User has not posted the login form yet: display the form
require( TEMPLATE_PATH . "/admin/loginForm.php" );
}

}



I chose to hash the username as well, and will probably add a second password. This is a single admin site, so I can stand to use multiple passwords. Not sure if also hashing the username helps at all with obscurity.

To avoid posting the username to the site, I change the function to ADMIN_USERHASH. I added a generic value to ADMIN_USERNAME, ie. "WebMaster".

To generate the hash values to place in config.php, you need to create and run a php file ie. hash.php

<?php
$salt = "whatever you want to put here"; // use same value in your function login
$login = "username"; // Put the username you will log in with here
$pass = "password"; // Put the password you will log in with here
echo hash('sha512', $salt . $login);
echo " - userhash";
echo "<br />";
echo hash('sha512', $salt . $pass);
echo " - password";
?>

Save this file somewhere safe, not on your webserver, after you generate your hashs.

My config.php looks like this:


<?php
ini_set( "display_errors", true ); // true for debugging, false for live site.
date_default_timezone_set ( "America/Chicago" );
define( "DB_DSN", "mysql:host=localhost;dbname=#####" );
define( "DB_USERNAME", "########" );
define( "DB_PASSWORD", "########" );
define( "CLASS_PATH", "classes" );
define( "TEMPLATE_PATH", "templates" );
define( "HOMEPAGE_NUM_ARTICLES", 5 );
[b]define( "ADMIN_USERNAME", "WebMaster");
define( "ADMIN_USERHASH", "this is where you put the hash generated with the previous file, generated from your username" );
define( "ADMIN_PASSWORD", "this is where you place the password hash" );[/b]
require( CLASS_PATH . "/Article.php" );
require( CLASS_PATH . "/Category.php" );
?>


My algorithm uses "salt", which helps further protect your information. I also am using sha512 to generate the hash, because, it seems the most secure algorithm PHP supports.
Hashing the username is completely optional. I might be overly paranoid. Forgive my lack of expertise, I am just now learning this stuff, as well. I hope this helps someone, I had a long day going thru alot of web pages to get this far.
28-Feb-12 21:38
@csturner

Thank you. i'm looking for something to arise my site's security.
let's me explore your code, it might suit my site some way.

thanks again.
29-Feb-12 01:51
Hello,

What kind of licence this CMS holds?

Thanks
29-Feb-12 04:40
Hi all again

I have got one practical question.

All my articles are being saved on the archive page. What if one day let's say, I'll have 2000 articles. Would that mean that all articles will be saved on one page -> archive.php and you'll have to scroll to get to the first one which will be on the bottom or is there any way that they could be managed and sorted by month?
29-Feb-12 06:50
If I want a thumnail picture on the mainpage (overview) and the main picture in the details page, would that be much work?
29-Feb-12 12:02
I started working out a way to add images and I have it working with minor bugs. But I'm no PDO expert so I'm curious if there is an easier way.

First I created another column in my database called 'photo' with a type of LONGBLOB.

In editArticle.php, I have :


<form action="admin.php?action=<?php echo $results['formAction']?>" method="post" enctype="multipart/form-data">
...
<label for="photo">Choose a file to upload:</label>
<input type="file" name="photo" id="photo">
...


Then I updated Article.php accordingly to add the new column. Under update(); (just working on this function for now), I added:



public function update() {
// Does the Article object have an ID?
if ( is_null( $this->id ) ) trigger_error ( "TechCard::update(): Attempt to update a Tech Card object that does not have its ID property set.", E_USER_ERROR );

$imgfp = fopen($_FILES['photo']['tmp_name'], 'rb');

// Update the Article
$$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "UPDATE articles SET publicationDate=FROM_UNIXTIME(:publicationDate), title=:title, summary=:summary, content=:content , photo=:photo, WHERE id = :id";
$st = $conn->prepare ( $sql );
$st->bindValue( ":publicationDate", $this->publicationDate, PDO::PARAM_INT );
$st->bindValue( ":title", $this->title, PDO::PARAM_STR );
$st->bindValue( ":summary", $this->summary, PDO::PARAM_STR );
$st->bindValue( ":content", $this->content, PDO::PARAM_STR );
$st->bindValue( ":photo", $imgfp, PDO::PARAM_LOB );
$st->bindValue( ":id", $this->id, PDO::PARAM_INT );
$st->execute();
$conn = null;
}



It seems to be added to the database just fine. I know getting it to show in the article will be another challenge for me, and I'm aware that my current code has some bugs. Putting that aside, is there an easier way or am I on the right track. Ideally, I would like the database to store the file name so that it is easier to retrieve. However, I couldn't get it working using PDO.
29-Feb-12 12:03
I started working out a way to add images and I have it working with minor bugs. But I'm no PDO expert so I'm curious if there is an easier way.

First I created another column in my database called 'photo' with a type of LONGBLOB.

In editArticle.php, I have :


<form action="admin.php?action=<?php echo $results['formAction']?>" method="post" enctype="multipart/form-data">
...
<label for="photo">Choose a file to upload:</label>
<input type="file" name="photo" id="photo">
...


Then I updated Article.php accordingly to add the new column. Under update(); (just working on this function for now), I added:



public function update() {
// Does the Article object have an ID?
if ( is_null( $this->id ) ) trigger_error ( "TechCard::update(): Attempt to update a Tech Card object that does not have its ID property set.", E_USER_ERROR );

$imgfp = fopen($_FILES['photo']['tmp_name'], 'rb');

// Update the Article
$$conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
$sql = "UPDATE articles SET publicationDate=FROM_UNIXTIME(:publicationDate), title=:title, summary=:summary, content=:content , photo=:photo, WHERE id = :id";
$st = $conn->prepare ( $sql );
$st->bindValue( ":publicationDate", $this->publicationDate, PDO::PARAM_INT );
$st->bindValue( ":title", $this->title, PDO::PARAM_STR );
$st->bindValue( ":summary", $this->summary, PDO::PARAM_STR );
$st->bindValue( ":content", $this->content, PDO::PARAM_STR );
$st->bindValue( ":photo", $imgfp, PDO::PARAM_LOB );
$st->bindValue( ":id", $this->id, PDO::PARAM_INT );
$st->execute();
$conn = null;
}



It seems to be added to the database just fine. I know getting it to show in the article will be another challenge for me, and I'm aware that my current code has some bugs. Putting that aside, is there an easier way or am I on the right track. Ideally, I would like the database to store the file name so that it is easier to retrieve. However, I couldn't get it working using PDO.
01-Mar-12 02:39
What about doing a Autoload class, then we won't neeed to require pages...

Maybe someone knows how to do that?
01-Mar-12 04:23
[b]I'm sorry, I'm having a problem with database connection
im useing appsever
can you please fix it for me[/b]
Fatal error: Uncaught exception 'PDOException' with message 'invalid data source name' in C:\AppServ\www\cms_\classes\Article.php:103 Stack trace: #0 C:\AppServ\www\cms_\classes\Article.php(103): PDO->__construct('DB_DSN', 'root', 'root') #1 C:\AppServ\www\cms_\index.php(40): Article::getList(5) #2 C:\AppServ\www\cms_\index.php(14): homepage() #3 {main} thrown in C:\AppServ\www\cms_\classes\Article.php on line 103
01-Mar-12 04:59
@csturner: No, you want magic_quotes_gpc to be off, otherwise quotes in data sent from your forms will be escaped. Or if you can't turn it off, you can test for it and run stripslashes() as I indicated earlier:

http://www.elated.com/forums/topic/5114/#post21628

I tend to agree with you that Disqus etc is a nice solution (and a lot easier!). However I might still write a comments tutorial just to show how it's done.

Also, nice hashing solution

--
Matt Doyle, Elated
01-Mar-12 05:22
@user89: It doesn't have a formal licence. Essentially though, I'm happy for people to use and adapt the code as long as they include an attribution and link to the article ( http://www.elated.com/articles/cms-in-an-afternoon-php-mysql/ ) somewhere that's publicly visible. I guess it's essentially similar to http://creativecommons.org/licenses/by/3.0/ . I might formalise this at some point.

Really though, this code is simply meant to be a tutorial to teach you how to use PHP and MySQL to build a CMS. I hope that readers can take the ideas in the tutorial and use them to build their own, more fully-featured CMS that suit their needs.

--
Matt Doyle, Elated
01-Mar-12 09:41
mod_rewrite is giving me a migraine. Why does every iteration of software have to change the rules?

I'm just trying to go from http://#######.com/?action=viewArticle&articleId=1
to something like
http://########.com/2012/02/29/titleofarticle

That is the proper way to improve seo, right?
01-Mar-12 20:41
@csturner

i have done something like this


RewriteRule ^articles/([^/]*)/([^/]*)/([^/]*)\.html$ /articles.php?action=$1&articleId=$2&url=$3 [L]


before $ is new look of our url, and after that is old look (real format of our url).
([^/]*) mean match any character.

this we will have

www.xxxxxx.com/articles/view/12/title-of-article.html

instead of

www.xxxxxx.com/articles.php?action=view&articleId=12&url=title-of-article.html

and php generate our link would like


<a href="/articles/view/<?php echo $article->id ?>/<?php echo str_replace(array(" "," "),"-",$article->title); ?>.html">

i'm use str_replace(array(" "," "),"-",$str) to replace space and double space with -.

if you need some thing of that you want.

change mod_rewrite to

/articles.php?action=$1&articleId=$2&year=$3&month=$4&day=$5&url=$6 [L]

and new look

^articles/([^/]*)/([^/]*)/([0-9]+)/([0-9]+)/([0-9]+)([^/]*)\.html$

*([0-9]+) match only number with 1 or more

and your php generate link would like this


<a href="/articles/view/<?php echo $article->id ?>/<?php echo date("Y",$article->publicationDate) ?>/<?php echo date("m",$article->publicationDate) ?>/<?php echo date("d",$article->publicationDate) ?>/<?php echo str_replace(array(" "," "),"-",$article->title); ?>.html">


we still need article's id because we look up our MySQL through id.

final result of your link

xxx.com/articles/view/12/2012/03/02/title-of-article.html

look like real static link!

may be you can move our id to show with url like

"12-title-of-article.html"

just change arrangement in link and mod_rewrite.

ps. hope you understand my english.
another ps. i haven't test ([0-9]+) regex before.

[Edited by chotikarn on 01-Mar-12 21:04]
01-Mar-12 22:05
@AdamBarry (and everyone else): I've just updated this tutorial and http://www.elated.com/articles/add-article-categories-to-your-cms/ to include the exception handler in config.php, so that PDO exceptions are never displayed on-screen. Code downloads also updated.

--
Matt Doyle, Elated
03-Mar-12 05:16
Thanks for you tutorials.i followed everything that u said and after i have hosted it on my server,this is the error message that i receive.pls assignment me...
=================================
Fatal error: Class 'PDO' not found in /var/www/ip/ex1/cms/cms/classes/Article.php on line 104
=======================
Expecting ur response soon.
Thanks...
03-Mar-12 08:11
@matt

thanks for your update.

@boge123

look like your PDO extension doesn't enable yet.
03-Mar-12 08:34
How do you allow multiple users? Also, is it possible for free registration and permissions for each member?

--
Cheers!
Aditya
03-Mar-12 19:18
@matt how can i do that?..pls guide me. expecting your response.Thanks...
04-Mar-12 09:53
@Matt Hi i have a question it is a bit off topic still

Q) I saw many hosting provider provide mysql db with 1GB space
and with unlimited plan you get like 1GB unlimited amount of db. As you can see the space is 1GB for each db then how can i move to another db or when the 1GB space is full.
I mean do i hv to make new db and manually check for db space and if i need to make new db how do i access it cos i hav for instance two db to access data.

How do big website cope with this problem

Thx Matt for the tutorial again
04-Mar-12 10:09
Matt, excellent tutorial.

From reading through all the comments above (including some of your helpful hints) I’ve been able to piece together how to successfully upload images in the back end and view them in the front end – although it took me a while as I’m really no expert. I wondered if you could give me any suggestions on how to hide any empty image fields (more difficult than hiding a text field).

Here's the code I added to the homepage to retrieve the image file..


<img src="/cms/images/<?php echo htmlspecialchars ( $article->image )?>">


Any hints would be gratefully received. Thanks again for posting this tutorial.

Chris
04-Mar-12 23:45
@Janjetina: I plan to address pagination in a future tutorial. See comments earlier in this topic.

--
Matt Doyle, Elated
04-Mar-12 23:47
@liholen: Shouldn't me much work. I plan to address image upload in a separate tutorial.

Autoloading will only load class files. Since there's only 1 class file in this tutorial, autoload would be overkill.

--
Matt Doyle, Elated
04-Mar-12 23:55
@pacothelovetaco: I never store my images in a database. Just store them as image files in the folder, and store the image filenames in the database table.

It's certainly possible to store images as blobs in the database, but I wouldn't recommend it. Let the web server serve the image files - it's what web servers are good at

I added some hints on image uploading earlier in this topic.

--
Matt Doyle, Elated
05-Mar-12 00:05
@phaohoa: Sounds like you haven't defined the DB_DSN constant in your config.php, or you've quoted the constant name in your PDO call.

--
Matt Doyle, Elated
05-Mar-12 00:27
@adityasaky: You mean multiple admins? I mentioned a hack for 2 admins here: http://www.elated.com/forums/topic/5391/

If there's enough demand for full-fledged multiple admin support then I may write a tutorial on it.

I don't understand what you mean by "free registration and permissions for each member".

--
Matt Doyle, Elated
05-Mar-12 01:07
@chotikarn, but how do i enable it.pls guide me.Thanks
05-Mar-12 06:58
first check your php information by

creat new php file name phpinfo.php

and add this code in it

<?php
phpinfo()
?>


if your PDO was Enable you will find it.

if it not enable yet, you should to config your php.ini by delete semi-colon in front these line

extension=php_pdo.dll
extension=php_pdo_firebird.dll
extension=php_pdo_informix.dll
extension=php_pdo_mssql.dll
extension=php_pdo_mysql.dll
extension=php_pdo_oci.dll
extension=php_pdo_oci8.dll
extension=php_pdo_odbc.dll
extension=php_pdo_pgsql.dll
extension=php_pdo_sqlite.dll

more information should be here.

http://www.php.net/manual/en/pdo.installation.php
09-Mar-12 17:51
@chrisbailey: Just use a conditional statement, for example:


<?php if ( $article->image ) { ?>
<img src="/cms/images/<?php echo htmlspecialchars ( $article->image )?>">
<?php } ?>


That way, the img tag won't be added to the page if the 'image' field is empty.

--
Matt Doyle, Elated
19-Mar-12 22:57
I want to use tbl_articles instead of articles.

Will I only need to change SQL statements i.e.:


$sql = "UPDATE [b]articles[/b] SET publicationDate=FROM_UNIXTIME(:publicationDate), title=:title, summary=:summary, content=:content WHERE id = :id";


to


$sql = "UPDATE [b]tbl_articles[/b] SET publicationDate=FROM_UNIXTIME(:publicationDate), title=:title, summary=:summary, content=:content WHERE id = :id";


--
- Web Dev Nub
21-Mar-12 00:27
can i ask the username and password of the admin? cant open the open the admin page...and also the index, won't run...can somebody help me?
21-Mar-12 15:27
Read the code in config.php and you will find it there!

--
Chris.
So long, and thanks for all the fish.
http://webmaster-talk.eu/
21-Mar-12 17:11
Oh and!

Make sure you change it if you are deploying the CMS on a live server.

--
Chris.
So long, and thanks for all the fish.
http://webmaster-talk.eu/
23-Mar-12 03:39
@michaelgc: Yes.

--
Matt Doyle, Elated
23-Mar-12 08:01
@matt, by free registrations, I meant anyone should be allowed to sign up to the site. And permissions as in, some may have permission to post, while others can edit. Like that.

This post is probably a bit late but my exams are on! Sorry.

--
Cheers!
Aditya
23-Mar-12 10:24
Is it possible to produce the list of archived articles in the header, so that there is an instant access to all the articles on a sidebar while still producing results for each of the pages? I've attempted the following.


<?php foreach ( $results['articles'] as $article ) { ?>
<br><a href=".?action=viewArticle&amp;articleId=<?php echo $article->id?>"><?php echo htmlspecialchars( $article->title )?></a>
<?php } ?>


While each function in the index and admin files not using getList has been modified with:


$data = Article:getList();
$results['articles'] = $data['results'];


But it registers the Limit set by the homepage.

[Edited by ares on 24-Mar-12 09:43]
24-Mar-12 19:58
Hi again!

I have encountered another "problem". Well everything is working fine with the ckfinder and whatnots, but I had an idea when I saw the new "add article categories" to the cms.

My idea is kind of basic really, its about echo out the different Article Categories to the header in links, like:

<a href=".?action=archive&amp;categoryId=3">
<?php echo ( $results['categories'][$article->categoryId=3]->name )?></a>

so the user can change the names of the categories easy.

Its working without any problem, but when I access an Article, The "<?php echo ( $results['categories'][$article->categoryId=3]->name )?>" (or echo name of category) does not work, and it displays blank.

Ive tried to configuration the Index, but no success.
For an example of what i mean, visit: guolldo (dot] com/cleancode/
and click on a Article, and look in the header-menu.

Can anyone help me figure this out or maybe give any hint?

And Matt, this tutorial have enlighten me with the whole mysql & php combo and possibilities, its awesome! THX 4 M!11!0n!!
26-Mar-12 02:09
@jj



<?php
include 'config2.php';
$query = "SELECT id, name FROM categories";
$result = mysql_query($query);
$numrows = mysql_num_rows($result);
while($row = mysql_fetch_array($result))
{
echo "<li><a href=.?action=archive&amp;categoryId=$row[id]>$row[name]</a></li>";
}
?>


You can achieve what you want with this code. Please note that config2.php is the file containing the info for the database.

Hope this helps
27-Mar-12 00:02
@adityasaky: Well you'd need to build a Members table and Member class, with methods to allow registration and login/logout. Add a 'permissions' property to the class to specify what the member can or cannot do.

--
Matt Doyle, Elated
28-Mar-12 11:32
Excellent tutorial, I'm close to getting it to work (had a slight slip up on the kb), thanks a lot for your insightful tutorial.
29-Mar-12 03:00
@ares: No idea without seeing all your code. The snippets you posted should work. Perhaps $results['articles'] is getting overwritten by the shorter list later in the index.php code?

--
Matt Doyle, Elated
29-Mar-12 10:24
Thanks for the reply. As you said it was overriding, I would need two separate arrays for it to work in the index, so I ended up solving it by removing the article limit, and adding a loop-break clause with a limit in the homepage.
29-Mar-12 18:39
Hi,
I have had a good mess around with the code but have got a little stuck trying to modify...

I would like to add an author id which is an integer, so I created the field in the database but am not sure how to get the author string to update as the correct author id when adding to/modifying the database.

I have:


if ($author1=="Bob")
$authorID = 1;
elseif ($author1=="Jane")
$authorID = 2;
else
$authorID = 3;


but don't know how to pass the author name into the variable author1.
When editing a record it works to just get $results['article']->author but when adding a new record that textbox is not populated until it is $_POSTed.


I also changed the Article class to include
[CODE]$st->bindValue( ":authorID", $this->authorID, PDO::PARAM_INT );
[/code]
and other places like that, I have managed to get it to add to the database, but not populate the authorID column.

Thanks for your time, I hope I explained well enough

[Edited by AWE on 29-Mar-12 18:40]
30-Mar-12 17:51
@Matt
hi matt, hope u doing good.
i went through the forum , to check wheather my question was answered before.

Our CMS get the news articles first. order by date DESC.
but what about if publish 10 articles a day and i want that the news article displayed at the top of the page by time. For example i published 10 articles today, date is same. But different hours and i want to see the news articles by time (hour) displayed at the top.

As we have already got date field in our database, i wonder wheather i could modify or need another additional field which holds my timestamp.
headlines.
>Microsoft anounces IE 9 date published and time.
>Microsoft anounces IE 10 date published and time.
>Microsoft anounces IE 11 date published and time.
Thanks
30-Mar-12 18:32
@mubuuba

i had finish modified code to handle date and time, and have a hint to other guy in this topic.

but you need to show only today article

MySQL might help you, here to code
"WHERE publicationDate = CURRENT_DATE"
you can also use GROUP BY to count number of your today article.
31-Mar-12 01:10
@Matt, I want people to be able to register directly using a register form. Can you do a tutorial on that?

--
Cheers!
Aditya
31-Mar-12 05:53
HI guys,

Awesome tutorial, it was really helpful especially how you went through most of the lines of the code.

Im having just one issue (i think). Im running the site on my MBP by using XAMMP. When i view the site i get this message

"Sorry, a problem occurred. Please try later."

i have gone through the code a few times now trying to work out where i went wrong. Im about to download the demo site to see if i can get it working that way.

Thanks
Jason
31-Mar-12 08:42
@jasonf
Open the config.php -file and look at these lines:

define( "DB_DSN", "mysql:host=localhost;dbname=YOURDBNAME" );
define( "DB_USERNAME", "root" );
define( "DB_PASSWORD", "" );


Your username is probably "root", and if you have not created a password, then let it be blank.
Also, if you havent, create the database in phpmyadmin with the .sql file

--------

@metalsniper63
Thank you for the code, but it is not working for me..
I think it is because I have used the "CMS with Articles"-tutorial.
Maybe any other idea?

Best regards,
JJ
01-Apr-12 22:59
@jj

Thank you so much it worked. I had the database name right it was just that my user name was "root"

thanks again
Jasonf
03-Apr-12 19:48
@metalsniper63 & everybody else that are interested

I'm trying to echo out the category names as links to the different categories in my header in a smart way, but I can not figure it out
Maybe any suggestion on what to do?

I've used the code from: metalsniper63 (Thanks btw )

<?php
include 'config.php';
$query = "SELECT id, name FROM categories";
$result = mysql_query($query);
$numrows = mysql_num_rows($result);
while($row = mysql_fetch_array($result))
{
echo "<li><a href=.?action=archive&amp;categoryId=$row[id]>$row[name]</a></li>";
}
?>


And it gives me:
"Fatal error: Cannot redeclare handleException() (previously declared in /Sites/the_site/config.php:15) in /Sites/the_site/config.php on line 18"

When I investigate the problem in config.php, I find:

function handleException( $exception ) {
echo "Sorry, a problem occurred. Please try later.";
error_log( $exception->getMessage() );
}
set_exception_handler( 'handleException' );

(code included in the cms with articles)
But, as I am (still) very new to PHP, and got no one to ask, I try to reach out here to solve this problem

Anybody who's got an idea of what to do?

Best regards,
JJ
04-Apr-12 10:19
@jj

Well what i would do (and did) is to create a new config file (with i called config2.php) with only the info to connect to the database:


<?php
$dbhost = 'localhost';
$dbuser = 'user database';
$dbpass = 'password for the database';
$dbname = 'database name';
$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die ('Error connecting to mysql');
mysql_select_db($dbname);
?>


It should now work with my code, just include config2.php instead of config.php.

Also i have this little code to show a "recent post" menu:



<ul>
<?php
include 'config2.php';
$action = isset( $_GET['action'] ) ? $_GET['action'] : "";

switch ( $action ) {
case 'archive':
archive();
break;
case 'viewArticle':
viewArticle();
break;
}
$query = "SELECT id, title FROM articles ORDER BY id DESC LIMIT 6";
$result = mysql_query($query);
$numrows = mysql_num_rows($result);
while($row = mysql_fetch_array($result))
{
echo "<li><a href=index.php?action=viewArticle&amp;articleId=$row[id]>$row[title]</a></li>";
}
?>
</ul>




Again this uses the config2.php file.

Hope this helps you and anyone who wants it


You can see it working here: http://www.standartdgo.com in the Blog section.

I have also added a Comments box from Facebook that changes for every article, if you want it just tell me

[Edited by metalsniper63 on 04-Apr-12 10:26]
04-Apr-12 19:52
@metalsniper63

Woohhaa! Or as we say in Swedish 'Fan va gött!'.
That did the trick. I just called in a db connection and executed the php, really good. Thanks amillion!

I'm really interested about the Facebook-comments box I have right now a dynamic Facebook 'Like' button, and a Tweet. If someone is interested, let me know also. But if I also can add an dynamic comment field it would be darn awesome!

I think you will help out allot of people with that code, caus now I start to understand the brilliance of PHP + MySql, it cool!

Thanks again!
Best regards,
JJ
05-Apr-12 01:25
Ok for all that want Facebook comments on your articles here is the code:



<script language="javascript" type="text/javascript">
var uri=document.location.href; //get uri
var isFbPrm=uri.indexOf('fb_comment');
if (isFbPrm!=-1) { // fb comment url
try {
var prm=uri.split("?"); //get paramaters
var url=prm[0]; //url
var prmItm=prm[1].split("&"); //parameter items
var newPrmlst='';
var newUrl='';
for(var j = 0; j < prmItm.length; j++) //read all param to get rid of fb param
{
var prmId=prmItm[j].split("="); //get param id

if (prmId[0]!='fb_comment_id'&&prmId[0]!='notif_t'&&prmId[0]!='ref') { //if parameters are not in the list
newPrmlst +=prmId[0]+'='+prmId[1]+'&';
}
}
uri = url+'?'+newPrmlst;
}
catch (err) {
//Handle errors here
}
}
document.write("<div id='fb-root'></div><fb:comments href='"+ uri +"' num_posts='10' width='730'></fb:comments>");
</script>
<script src='http://connect.facebook.net/es_LA/all.js#xfbml=1'></script>




I didn't make this code, i just don't remember where i got it from hahaha. just change the "script src" line to your local script and that's it.

I placed this code in the viewarticle.php file. i think is really self explanatory. Happy coding
05-Apr-12 06:01
@AWE: Not sure I understand totally. Sounds like you want to have different article authors, yes? The best way would be to create an authors table with unique ids and author names and create a corresponding Author class, then add an authorId column to your articles table and a corresponding $authorId property to your Article class. Then in index.php etc you can call Author::getList() to get all the authors and store them in an array keyed by ID (much like I show with categories in http://www.elated.com/articles/add-article-categories-to-your-cms/ ). Then, whenever you need to display the article's author, just use something like: $results['authors'][$article->authorId]->name .

--
Matt Doyle, Elated
05-Apr-12 16:41
Does anyone know how i can get the form in editArticles to have a field which had a drop down menu which is populated from a different database with a list of items?

ian
08-Apr-12 05:11
Does anyone know how I can make the publication date in to a drop down menu?
18-Apr-12 08:01
Hi!

Firstly, thanks for an amazing tutorial! I've adapted this for heaps of uses (comments/images etc.) now I'm trying to do something probably pretty simple but just can't seem to do it elegantly..

I want to simply be able to make a post a primary post and want it to display first :\ Ive tried this by using a column in my DB setting a specific row to PRI. Can I write an SQL statement to update a value of a row while sort of deleting another (so when a new post is set PRI the old one is no longer PRI),

Hope I'm making sense and thanks for any help

Jarrod.
19-Apr-12 05:51
after i run this code in xampp installed on windows os it shows a error message ('system error try again later').
please help
19-Apr-12 14:39
@shev

Dude, check out the config.php - file, and enter the correct username, passw & DataBase-name. For Mac os, the default uname is root, and no pword.

Try it out!
/J
20-Apr-12 09:45
Hi Matt, this looks like a fantastic facility thank you very much.

The only small problem is that I cannot even pass go. I get the message

"Sorry, a problem occurred. Please try later."

I have searched the forum and the only other example was solved by a user name and password issue. This does not appear to be my problem. Here is my config file.

<?php
ini_set( "display_errors", true );
date_default_timezone_set( "Africa/Harare" ); // http://www.php.net/manual/en/timezones.php
define( "DB_DSN", "mysql:host=localhost;dbname=cms" );
define( "DB_USERNAME", "root" );
define( "DB_PASSWORD", "" );
define( "CLASS_PATH", "classes" );
define( "TEMPLATE_PATH", "templates" );
define( "HOMEPAGE_NUM_ARTICLES", 5 );
define( "ADMIN_USERNAME", "admin" );
define( "ADMIN_PASSWORD", "mypass" );
require( CLASS_PATH . "/Article.php" );

function handleException( $exception ) {
echo "Sorry, a problem occurred. Please try later.";
error_log( $exception->getMessage() );
}

set_exception_handler( 'handleException' );
?>

I do not have any spaces at either end of the file.
I set up the database and fields using the sql file provided and do not have a password for my root user.

Any help will be appreciated.

Many thanks
21-Apr-12 13:36
function handleException( $exception ) {
echo "Sorry, a problem occurred. Please try later.";
error_log( $exception->getMessage() );
}


Read the error log to see what caused the exception.

--
Chris.
So long, and thanks for all the fish.
http://webmaster-talk.eu/
22-Apr-12 04:17
Hi,

I tried adding an upload/download feature on your CMS, but it doesn't seem to work for me, i'm a PHP MYSQL newbie, and i want to learn more... I'm trying to make each topic be able to upload any file, for example, a word document, for users to download..

Thanks for this article, i learned many on this, including on PHP classes, functions etc.

Or if you have extra time, can i request an additional article for adding an upload/download feature on your CMS in afternoon.. please...

Thanks,
MARK B.
22-Apr-12 05:32
@chrishirst

Thanks for the reply. I am too much of a newbie to know how I can go about reading the error log. Further advice would be appreciated.

Many thanks
22-Apr-12 07:47
error_log is a text file (no extension) that is located in the root folder of your website that PHP can/will/does write information about non-fatal errors and exceptions.

It should tell you what the code tried to do and the script that it occured.

--
Chris.
So long, and thanks for all the fish.
http://webmaster-talk.eu/
23-Apr-12 02:35
@snookian: Depends on exactly what you want to do, but generally I would create a class that maps to your database table (much like Article.php maps to the articles table), and add a getAll() method that retrieves all the objects from the table. Then call getAll() whenever you want to display the form, and loop through the resulting objects to display your select menu. You'll presumably also want to add an "object id" field to your Article class to associate the selected object with the edited article (assuming that's what you want to do).

@Micheal: Again, there are many ways to do this. You'll probably find that something like this is the easiest: http://jqueryui.com/demos/datepicker/

@alteran: By PRI do you mean the table's primary key? Primary keys are for uniquely identifying database rows - you should not use them for anything else. If you just want a particular article to always appear at the top of the list then create a "primary" boolean column and set it to true or false, then order your results by the primary column, followed by date (eg "ORDER BY primary DESC, publicationDate DESC").

@markbaronelated: I've added file/image upload to the list of future tutorial ideas.

--
Matt Doyle, Elated
23-Apr-12 05:36
@chrishirst

Thanks for the help.

The php log is as follows;
[23-Apr-2012 12:05:26] could not find driver

While the access log is as follows;
127.0.0.1 - - [23/Apr/2012:12:05:24 +0200] "GET / HTTP/1.1" 200 6570
127.0.0.1 - - [23/Apr/2012:12:05:26 +0200] "GET /cms/ HTTP/1.1" 200 44

I use WAMP 5
php 5.2.3
Mysql 5.0.41

STOP PRESS .........

Good news is that I have sorted out my problem. Just upgraded to WAMPSERVER 2.2 which sorted the driver problem.
Bad news is that I lost my databases in the process, but I should manage to reconstruct.

This CMS utility looks fantastic. Thank you very much

[Edited by Zimbo on 24-Apr-12 08:37]
24-Apr-12 08:59
Warning: require(classes/Article.php): failed to open stream: No such file or directory in /var/www/cms/config.php on line 12 Fatal error: require(): Failed opening required 'classes/Article.php' (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/cms/config.php on line 12



hi guys,am getting the above error after following your steps to the letter. help please

--
none
24-Apr-12 12:53
And are you running PHP on Windows?

--
Chris.
So long, and thanks for all the fish.
http://webmaster-talk.eu/
24-Apr-12 16:42
nope...am running apache2 on linuxmint. but i also tried the project on win7 and xampp and still got the same error. any way around it?

--
none
25-Apr-12 12:39
Windows I can understand because of the different folder/drive structures. Mint, I don't know what the default paths are yet as i'm just setting up my first mint box up, Centos is normally my weapon of choice when it comes to Linux. Is "pear" installed and on that particular path?

[Edited by chrishirst on 25-Apr-12 12:40]

--
Chris.
So long, and thanks for all the fish.
http://webmaster-talk.eu/
26-Apr-12 20:12
Hi all,

This is a great CMS, but i'm having some issue with using youtubes code for embedding youtube videos.

I find that when I save to the database it adds "\" all the way along the embed code

<iframe width=\"640\" height=\"360\" src=\"http://www.youtube.com/embed/1obZFdfL4TM\" frameborder=\"0\" allowfullscreen></iframe>


Is there anyway of stoppping this from happening?

Thank all
David

[Edited by slayerscout on 26-Apr-12 20:13]
02-May-12 00:50
Great tutorial.

Question about Admin login link on the webpage.

The Admin Login (site admin) link is currently on the same page as blog template.

Can I implement a seperate login page that is not viewable to the public, just to add another level of security. Basically, when I update by webpage/blog contents, I do it via a different personal page.
03-May-12 04:52
Hey, first of all, thanks for the great tutorial, it's helped me a lot, but unfortunately I'm having one problem currently (Similar to slayerscout's)

http://justanotherrandomsite.com/ I've uploaded it to my site, but when I create links or ('s) it keeps adding "\'s" in the code.

It also messes up the links so I can't link to anywhere, because the links come out like (ex):




http://justanotherrandomsite.com\*www.vgchartz.com*\

(When linking to www.vgchartz.com

I didn't have this problem when developing on my PC, but now the website isonly and it occurs.

Any help would be appreciated, thanks.
04-May-12 15:49
Hey Matt,

Thanks for the great tutorial! I am in the process of learning web programming mostly from books and articles I am reading online. To help me in the process, I am actually taking the time to type the code myself instead of cutting and pasting. This is what I've done with your tutorial, and everything seems to be functioning okay except I can't get the articles to post to my database. I've checked the code several times alongside your original code. Everything seems to match up perfectly. Still won't post to the DB though. I either get the success message when I use the CMS as coded in your original example, or the "Please fill out this field" callout message appears on the upper left corner of my browser (Firefox) when I try to integrate tinymce with the form. Any ideas on where I am going wrong?

Thanks again!!! It always amazes me when people with your great skill take the time to write comprehensive tutorials like this one to help teach us "newbies".
04-May-12 19:23
@revjeff7

hi, about your problem. it seem that you have "required" parameter on your "textarea" tag. this should be work fine without any Text Editor such TinyMCE or CKeditor, but when you need to use it on textarea the "required" parameter have to remove.

if you still have "required" and have Text Editor, HTML will assume that textarea has on data on it and "Please fill this field" will appear but on my chrome 17 everything look freezing, not have any sign of error.

PS. hope it might help you.

[Edited by chotikarn on 04-May-12 19:23]
04-May-12 22:28
@chotikarn

Thanks! You were right about the "required" parameter with tinymce. I guess I need to look for a way to get around this and still be able to use the required parameter on the form. Also, I still can't get articles to post to my database.
05-May-12 05:22
@revjeff7

maybe jquery form validation might help.

do you re-check your code yet? re-check your typo "__construct" functioin "storeFormValues" and "insert" function.
05-May-12 15:35
Hi, I was wondering what I would have to edit to make it so instead of just year/month/day, I could make it year/month/day at HH:MM. I thought I had it down, but whenever I try it, it just displays the epoch. Any ideas?
10-May-12 04:39
@slayerscout @MarcusS: Search this topic for "magic quotes".

@vman: You could bookmark the link, then remove the link from the front-end template. If you're still worried about security, you could password-protect your admin script like this: http://www.elated.com/articles/password-protecting-your-pages-with-htaccess/

@ffxpwns: Here's the syntax for the PHP date() function: http://php.net/manual/en/function.date.php

--
Matt Doyle, Elated
10-May-12 10:29
@ matt

Thanks for the advice, I found the solution yesterday earlier in the topic.
15-May-12 06:13
Dear Matt.

First off let me thank you for your wonderful, concise and clear method of teaching. I am currently studying Networking and Administration at university and wanted to branch off and learn some PHP. I will defiantly be sharing your website around.

Following on from http://www.elated.com/forums/topic/5114/#post20643 I have pieced together a similar method to upload images in the editArticle.php however it appears that once I insert


$st->bindValue( ":imageId", $this->imageId, PDO::PARAM_STR );


Into the function () Insert and update, the entire article refuses to save to the database, and transfers me back to listArticles.php admin page without saving.

Article Class

ImageId is defined as


public $imageId = null;


In __construct, imageId is as follows


if ( isset( $_FILES['imageId']['tmp_name'])) $this->imageId = $data['imageId'];


In the function insert () and update ()



$st->bindValue( ":imageId", $this->imageId, PDO::PARAM_STR );
if ((($_FILES["imageId"]["type"] == "image/gif")
|| ($_FILES["imageId"]["type"] == "image/jpeg")
|| ($_FILES["imageId"]["type"] == "image/pjpeg"))
&& ($_FILES["imageId"]["size"] < 500000))
{
if (file_exists("articleImageLocation" . $_FILES["imageId"]["tmp_name"]))
{
echo $_FILES["imageId"]["tmp_name"] . " already exists. ";
}
else
{
move_uploaded_file($_FILES["imageId"]["tmp_name"], "articleImageLocation" . $_FILES["imageId"]["tmp_name"]);
}



I have a feeling that the way I have gone about the code to move the uploaded file is incorrect. Should it be under its own function INSIDE function insert/update? Should it come before or after $st->bindValue( ":imageId", $this->imageId, PDO::PARAM_STR );

editArticle.php

Inside editArticle.php, I have added the form/multidata tag, as well as



<li>
<label for="file">Image:</label>
<input name="imageId" type="file" "<?php echo( $results['article']->imageId )?>" />
</li>



Inside viewArticle.php, I have added the <img> code. Which is correct?



<img src="<?php $article->imageId )?>" alt="article image">


Now what I believed this would do, is it should send the results/location to Article::ImageID, which should then use the code in the Article class to send the image filename and location to the database field ImageId, (varchar(255)) which would then be fetched, along with the rest of the article, when that article is clicked on. What I believe and what I know though are two different things.

I’m not sure how much you could help me with just this code alone, I believe I am missing some pretty crucial code, but I have no clue what. When I SELECT * from articles; in mysql, the imageID field is blank.
Please and a massive thank you in advance if you could give me a hint as to what am doing wrong.
16-May-12 11:55
Any chance of you doing a tutorial on adding images or other media to the CMS articles.
17-May-12 04:58
@MarcusS: Glad you got it working!

@Farmman64 @jpkelly: I'm currently working on a followup CMS tutorial (due next week) that shows how to upload a single image for each article.

--
Matt Doyle, Elated
19-May-12 15:18
Problem:
<a href=\\\\\\\"
In index.php insert the code:
<?php
if (get_magic_quotes_gpc() == TRUE) {
ini_set('magic_quotes_gpc','off');

Welcome the http://rotflonline.pl

[Edited by rebelianto on 19-May-12 15:18]
19-May-12 21:37
Great news Matt!
Looking forward to the new tutorial on adding an image to articles.
22-May-12 16:42
Hello All...!

Very nice CMS system...! Works fine here...!

But, i want to add multiple admin accounts with DB...and not calling a solo "username" and "password" account from config.php...!

How to construct a multiple admin account based on DB using this plataform (CMS)...?

Basically this workaround is ready...but, i couldnt see a simple form to do this...!

Need some help, example or tut...simple and elegant as this tut...!

Thank you.
28-May-12 01:00
Any word on the progress of the adding images to articles tutorial?
28-May-12 07:18
Haha Kelly, im the same with the wondering. We shouldn't push and pester Matt though, he is doing this out of the kindness of his own heart!

Looking forward to it though!
28-May-12 10:56
Sorry.... I don't want to pester or be pushy.
31-May-12 06:13
Sorry for the wait guys! It took longer than expected, but here's how to add image uploads to your CMS.

http://www.elated.com/articles/add-image-uploading-to-your-cms/

Enjoy!
Matt

--
Matt Doyle, Elated
06-Jun-12 00:30
Big thanks, matt. your image upload are work well one me.

but i've a question about multiple checkbox.

i've multiple checkbox look like this



<input class="checkbox" name="color[]" type="checkbox" value="red">
<input class="checkbox" name="color[]" type="checkbox" value="blue">
<input class="checkbox" name="color[]" type="checkbox" value="green">


and need to store it's value in same column of table, is it a good idea? and how should it work on your CMS.

Thanks, Chotikarn.
06-Jun-12 09:13
Hi Matt,

First off I wanted to say THANK YOU for making this, I scoured the internet looking for a decent and easy CMS system and found yours.

Second off, I am a noobie programmer when it comes to PHP and MySQL, but I am having issues with the CMS system working and I'm not sure what to do.

http://pieforensic.com/test/admin.php

That is the link, however when I log in I get "Sorry, a problem occurred. Please try later."

I've setup the DB username and password correctly and I'm using the built in PHPmyadmin panel from host excellence to edit the settings for the db, which is called "sgold39_cms."

I'm not too sure why it's not connecting.
15-Jun-12 03:05
@Marki: See http://www.elated.com/forums/topic/5114/#post22468

@chotikarn: I would probably create 3 separate boolean fields in your articles table (red, blue, green), unless you want to have an arbitrary number of colours per article, in which case I'd create a 'colors' table and join it with the articles table.

@lowestofthekey: You could try commenting out the set_exception_handler() line in config.php to see the actual error message, or look in your website's error log for the error message.

--
Matt Doyle, Elated
15-Jun-12 10:52
Thank you, matt.

My question might not clear.
it's a multiple choice of checkbox.
i was try to "implode" value together but in MySQL filed still have "array" not "red,gree,blue" as i expected.

and i was try "serialize" and have something like "s:00 { red, green,blue } a:0".

any idea?

----------- Edit -------------
Now, i've done what i want but i use another hidden text-input and use jquery to map my checkbox value as array and send it to text-input, then use your cms engine to store it in mysql

it's work well.

[Edited by chotikarn on 15-Jun-12 13:36]
15-Jun-12 22:04
Matt

You write awesome articles. Could you please show an example of the proper use of Try .... Catch?

Thanks

Phil
17-Jun-12 03:22
I Matt!
I've seen you made this:


$sql = "SELECT SQL_CALC_FOUND_ROWS *, UNIX_TIMESTAMP(publicationDate)
AS publicationDate FROM articles

ORDER BY " . mysql_escape_string($order) . " LIMIT :numRows";

$st = $conn->prepare( $sql );
$st->bindValue( ":numRows", $numRows, PDO::PARAM_INT );
$st->execute();



Well, I would just ask you, instead of calling the "deprecated" mysql_escape_string, why not just go straight with PDO:


$sql = "SELECT SQL_CALC_FOUND_ROWS *, UNIX_TIMESTAMP(publicationDate)
AS publicationDate FROM articles

ORDER BY :order LIMIT :numRows";

$st = $conn->prepare( $sql );
$st->bindValue( ":order", $order, PDO::PARAM_STRING );
$st->bindValue( ":numRows", $numRows, PDO::PARAM_INT );
$st->execute();


?
From the PHP manual:

The parameters to prepared statements don't need to be quoted;
the driver automatically handles this.
If an application exclusively uses prepared statements,
the developer can be sure that no SQL injection will occur (however,
if other portions of the query are being built up
with unescaped input, SQL injection is still possible).


Please tell me if I'm in wrong!
Bye, best wishes.
17-Jun-12 11:47
Hi Matt

Thanks for the great script, but as you directed i created the database and afters directly imported your given tables.sql file in phpMyadmin, and filled the
db name which is cms, username and pass in config file.

i can't get about the admin username&pass, does it same as that of db or do i have to create one?

secondly, i get this error "Sorry, a problem occurred. Please try later."

pl advise me on this, as i always was looking for second option for wp. great stuff, thanks for availing it free.

Thanks
18-Jun-12 07:10
Look in config.php the default admin user and password is in there, and is NOT the same as DB user and password.

--
Chris.
So long, and thanks for all the fish.
http://webmaster-talk.eu/
18-Jun-12 12:54
Hello,
Thanks for your great article.
I've a really strange problem. When I create a new article and set its date to be 2012-06-18, it will be saved as 2012-06-17 and each time there is a date in the box, after saving, the date is 1 day before it !!!

I can not figure out how to fix it. Thanks for your help. I really appreciate it
26-Jun-12 02:02
@philatnotable: Thanks for the suggestion - I'll add a tutorial on PHP exceptions to the schedule.

@Antonio82: PDO parameter binding doesn't work with ORDER BY clauses.

@Sepehr: Sounds like you have a time zone mismatch between your MySQL server and your PHP script. Did you set the correct server time zone in your config.php?

--
Matt Doyle, Elated
17-Jul-12 19:36
Hello All...!

Anyone knows how to modify this great CMS to edit "time" in "publicationDate"...to save and to edit...?

I only got 00:00:00 time on my database...! I wish to edit this...!

I have some probs using "mktime" in "storeFormValues"...!

Many Thanks...!
18-Jul-12 08:14
Hi Matt, great tutorial! I'm just having a problem, I'm getting the error "try again later" it means some problem with the connection, I imported the database to my mysql database (wich means it's not local) and I put the name and password so I wonder what could be going wrong, I know that you say on the tutorial that you have to also put the database name (I didn't because with the mysql database you put the full location to find the database like "hostedresource...etc..etc), and in these cases I never had to put the db name.
19-Jul-12 09:24
I figured it out, I had to write the database name, now I want to ask you the best way to create a page for the user (admin) to register the username and password through a front-end (admin) page 'cause now, the admin username and password are set in the config code but if the person doesn't know coding or doesn't want to do that, how can they sign in? Thanks!
21-Jul-12 07:45
Hello Mr. Matt

First i would like to thank you for taking time to write these really helpful tutorials, i learned alot.

I merged all your PhP CMS scripts in one for my school project.

Now only thing i cant figure out is how to put some content on right next to my articles.

I highlighted the area i want to put some content with red color, so you can have idea what i want.

Here is the picture:

http://tinypic.com/r/3480lep/6

I would appreciate if you tell me step by step which .php and .css files i should change (note all .php files have original names that you made).

Thanks in advance.
21-Jul-12 15:52
@chotikarn I implemented the pagination code you provided and I think I implemented it correctly but for some reason when I click on the links (1, 2, Next...etc) the page doesn't show any articles. And then when I click Previous, that page doesn't show any articles either. I tried it using the original code from this site too but the same thing happens.

Would you or anyone here have any idea what I can do to get it working? Thanks.
27-Jul-12 02:25
@Marki: Use date() to format the date for the text field in the form, and explode() / mktime() to parse the date entered in the text field and convert it back to a timestamp.

@eddie: I don't understand your question totally. You need to start with a username/password at some point, and the easiest way is to hard-code them into config.php. The alternative would be to create some sort of default password (a potential security hole) and redirect the admin to a page on first login where they could reset their password.

@Dug: I'm not sure what you mean by "content" here. Static content? Put it in the viewArticle.php template.

@DOC: I might write a pagination tutorial if there's enough demand...

--
Matt Doyle, Elated
08-Aug-12 07:25
Thanks for your good tutorials!
I also have a question.If I wanna post articles in Chinese by using the simple cms,how do I need to modify?
08-Aug-12 17:54
Can someone help me out on adding 2 radio buttons with 2 different sizes for thumbnails? Instead of the constant one in i config.php.

I would also like to change the language of the months in the dates, any ideas on how to do this?

Thanks in advance!
10-Aug-12 02:17
@hd_199053: If you need to use Chinese characters then make sure you're using Unicode (UTF-8) throughout the whole process, from the HTML page encoding, through to any PHP string functions such as preg_replace() and, finally, the MySQL table encodings.

eg see the 'u' modifier at http://php.net/manual/en/reference.pcre.pattern.modifiers.php

This page should get you started: http://malevolent.com/weblog/archive/2007/03/12/unicode-utf8-php-mysql/

--
Matt Doyle, Elated
10-Aug-12 02:23
@srtu: You mean radio buttons for the administrator to choose thumbnail sizes, or for the user? More details needed please.

Dates: Use http://www.php.net/manual/en/function.setlocale.php to set your locale, then use http://www.php.net/manual/en/function.strftime.php to output the dates instead of date().

--
Matt Doyle, Elated
10-Aug-12 17:07
@matt
Thats correct. Using radio buttons for the administrator.

Was looking at set locale before but I didnt seem to make it work with Swedish, maybe I should just do a array for it?
22-Aug-12 09:06
Very useful and informative.

Thank you Matt
25-Aug-12 10:44
Hello there, i get this error please can anyone help me?

Warning: mysql_real_escape_string() [function.mysql-real-escape-string]: Access denied for user 'root'@'localhost' (using password: NO) in /home/u972373064/public_html/blog/classes/Article.php on line 105

Warning: mysql_real_escape_string() [function.mysql-real-escape-string]: A link to the server could not be established in /home/u972373064/public_html/blog/classes/Article.php on line 105


why does it says for user root@localhost?
i am running in a public mysql server with username and password both defined in config.php
15-Sep-12 05:01
Hi Matt, thanks for the brilliant tutorial! Very useful. I have a question though. On the homepage where it displays all of the articles, I have placed a search box (just a textbox within <form> tags and a submit button). This allows users to search for articles using the title. Im a little stuck on how I can perform the search using your current structure as I would like the results to display on screen as normal articles like on the homepage but filtered. Hope you or someone can help. Thanks
25-Sep-12 02:21
@jj007: I would modify the homepage() function in index.php to check for a 'searchQuery' parameter (or whatever your search field's called). If it exists and is non-empty, pass it as a third argument to Article::getList().

Then modify Article::getList() to check for the third parameter; if present, use it to add a WHERE clause to the SELECT statement that filters the returned articles to just those whose title contains the value of searchQuery.

--
Matt Doyle, Elated
08-Oct-12 11:52
What is the best way to perform good SEO on this setup? I have an index page which sends me to the home.php page which has information on including word through out the text that relates to metadata. On this page i also include the php header which contains a lot of my meta data yet it doesn't seem to work for google. Either having index.php to home.php doesn't work very well for SEO or including the header, has anyone managed to get it to be successful?
14-Oct-12 11:50
Hi Matt, Thanks a bunch for this cms, it looks awesome.

However I have not been able to get mine set up and working...

I have uploaded it to my website, I have created the database as follows, put my correct password, username etc on the config.php file as well as the correct time. And uploaded..

However I only get the error message
'Sorry, a problem occurred. Please try later..'

Here is the code for config.php - wonder if you can help at all?

(I have put the dbname and username in question marks for security reasons)


<?php
ini_set( "display_errors", true );
date_default_timezone_set( "GMT" );
define( "DB_DSN", "mysql:host=localhost;dbname=????" );
define( "DB_USERNAME", "????" );
define( "DB_PASSWORD", "cmsblog" );
define( "CLASS_PATH", "classes" );
define( "TEMPLATE_PATH", "templates" );
define( "HOMEPAGE_NUM_ARTICLES", 5 );
define( "ADMIN_USERNAME", "charliegreen" );
define( "ADMIN_PASSWORD", "bondaholic" );
require( CLASS_PATH . "/Article.php" );

function handleException( $exception ) {
echo "Sorry, a problem occurred. Please try later..";
error_log( $exception->getMessage() );
}

set_exception_handler( 'handleException' );
?>


Thanks, look forwards to hearing back.
17-Oct-12 20:15
Hello everyone! Thanks for this great tutorial!
I am trying to introduce clean urls but I can't do it...

I have my .htaccess exactly like this:


RewriteEngine On

RewriteRule ^articles/([^/]+)/?$ /?action=viewArticle&articleId=$1 [L]


I then refresh the main page (of localhost), and click an article.
The url stays the same (http://localhost/test/?action=viewArticle&articleId=1) why is this???

THANKS IN ADVANCE! THIS IS GREAT!
17-Oct-12 20:25
Ok, now I have managed to get to the article if inputting the adress manually (http://localhost/test/articles/1), shouldn't it redirect me automatically to this adress when clicking an article?

This is the code in my htaccess:



RewriteEngine On
RewriteRule ^articles/([^/]+)/?$ /?action=viewArticle&articleId=$1 [L]



And it keeps giving me problems because now, it's just a blank page without any images, where images should be there's an error (image not avaiable) because the the server is trying to acess the images in the following folder: (http://localhost/test/articles/images/logo.jpg)

Can someone please copy/paste the correct .htaccess code and homepage.php code for auto redirect to clean urls?

THANKS IN ADVANCE!
30-Oct-12 23:41
can i use this code in creating professional cms? because i am new to php. thanks,
20-Nov-12 05:41
Im having the same problem than avedus

Warning: mysql_real_escape_string(): in D:\xampp\htdocs\cms\classes\Article.php on line 105

Warning: mysql_real_escape_string(): A link to the server could not be established in D:\xampp\htdocs\cms\classes\Article.php on line 105

A few weeks ago it was working as a charm, but now I'm getting this error, it's while trying to get the total rows of article(s)

[Edited by firefly2024 on 20-Nov-12 05:47]
21-Nov-12 21:03
@firefly2024: Presumably you replaced the mysql_escape_string() call in the original tutorial with mysql_real_escape_string(), and either the link identifier you passed is invalid, or you didn't pass one and PHP can't connect to your MySQL DB using the default settings. Read more here:

http://www.php.net/manual/en/function.mysql-real-escape-string.php

Either make a connection yourself and pass a valid link identifier, or make sure your default MySQL connection parameters are correct, or stick with the original mysql_escape_string().

--
Matt Doyle, Elated
23-Nov-12 03:51
Hi everyone , do you know in that script where i can put mysql_query("set character_set_database='utf8'");
mysql_query("set names utf8");
17-Dec-12 15:46
@Geraki: See http://www.laszlo.nu/post/34159352/how-to-use-utf-8-with-mysql-and-php-data-objects-pdo

You shouldn't call "set character_set_database='utf8'" manually at all - see: http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_character_set_database

Just make sure you create your tables using the utf8_unicode_ci collation.

--
Matt Doyle, Elated
29-Dec-12 15:19
Hi Matt, great and helpful tut! Thanks for your expertise. I am wanting to play with the homepage and am wondering if it's possible to put the articles Table in an XML or JSON file, and then link data to an RSS feed to track new articles added. Is this possible? If you can provide an example and/or explanation of XML/JSON within the context of this tutorioal it would be very helpful to a lot of us.

[Edited by Jim22150 on 03-Jan-13 12:09]
07-Jan-13 09:11
@matt I was wondering how editArticle.php validates itself so it isn't submitted blank? because I can't seem to find any code for it?
13-Jan-13 22:59
@mikewkd2: What makes you think it does any validation?

--
Matt Doyle, Elated
21-Jan-13 12:31
I forgot about the existence the "required" tag in the inputs
I thought it was validating because I couldn't submit the form blank or with missing field
28-Feb-13 05:38
@matt I have used your tutorial a couple of times for different uses now and its great, However on this occasion im in need of help which im sure is dead simple im just having a dead brain moment, How do i insert a field (Couple of fields in the form) to an array, im unsure whether to change the form setup or the insert value in the Article. Nay help or guidance will be great.

Ian
04-Mar-13 16:29
HI all!

First off I just wanted to say a HUGE THANKS to Matt for posting this very helpful article

I have spent the better part of 2012 up to the present, expanding on this CMS framework. I have now created a github project for others to share in the development from here forward if anyone is interested: https://github.com/geraldbullard/gnscms

I have integrated the Charisma Fully Responsive Open Source Admin, a .simplesite Responsive theme for the front end and have recently started working on the menu system functionality...

The installer is not 100% complete but is there in the admin for the database schema.

Also I would love to have anyone work on pagination for the pages/settings listings in the admin and/or front end.

Again this system is FAR FROM COMPLETE and needs a good many small iterations to be widely acceptable as a stable release for any production sites, but is nonetheless fully capable of supporting live web sites with a little TLC

I hope you all enjoy what I have created from Matt's gracious contribution and please send those pull requests to add to this growing system!

======================================
NOTE: you will NOT recognize anything about the look of the admin or front end, only when you get into the class and layout areas will anything looks similar.

[Edited by geraldbullard on 04-Mar-13 16:31]

--
Gerald B
http://3g-dev.com/
04-Mar-13 20:39
geraldbullard, thanks you for share this. I gonna test your CMS soon as possible.

I was work around with matt's CMS too, and you give me other opportunities to improve my PHP skill.

Thanks.
04-Mar-13 21:33
Make sure to get the fresh zip from github tonight, I actually updated the installer and added a "show in menu" feature plus had to work on the 3 included templates on some overlooked issues...

just get the latest zip, from the development branch: https://github.com/geraldbullard/gnscms/tree/develop and upload to your site, then just hit the location in your browser and it should redirect you to the installation. Also one very important note...

you will have to update your .htaccess line from

RewriteBase /afternooncms/

to

RewriteBase /yourfoldername/ or the mod_rewrite will not work on the urls

if you are installing to the site root then that line should be

RewriteBase /

best of luck

[Edited by geraldbullard on 04-Mar-13 21:35]

--
Gerald B
http://3g-dev.com/
13-Mar-13 03:32
I have an Incredibly odd bug I was hoping you could explain.

Every time I save or update an article the publication date ends up subtracting one day from whatever the specified publication date is. For example: Publication date is listed as 2013-03-05 and once saved it will be shown as Mar 4 2013, now if go back and edit the article then hit save it will automatically subtract another day and be displayed as Mar 03 2013.

Any idea where this could be happening? I had used the default source code and only made small modifications to get it working on our web host and everything else but this odd bug works wonderfully.

Thank You
14-Mar-13 10:03
Im having issues dealing with special characters (in this instance the '&' character) in the title and summary fields of editArticle form. I am being returned blanks wherever they are used.

I pass content data through ckeditor for the content field and all charcters works fine there.

I have changed all pages to UTF-8 charset and my database also uses UTF-8, so now im not sure where the problem lies.

Any tips or solutions would be welcomed.

[Edited by andy_baz on 14-Mar-13 10:04]
16-Mar-13 21:56
@andy_baz

Check the 'public function __construct( $data=array() )' in the article class and take a look at ' preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['title'] ) '.

Matt has set the function to escape characters that could be used with malicious intent, read section '2. The constructor' to see if you want to bypass this safety step.

I've just been using characters that aren't being replaced; like using 'and' instead of '&'.

Cheers
23-Apr-13 13:41
I downloaded you files for the CMS but I have a database started already that is called events instead of articles. It also has more events. I am having issues getting the code edited to work with my databases. Here is the table.sql code so you can see my database. Please help! hotmail is rhonda8181

-- phpMyAdmin SQL Dump
-- version 3.5.1
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Apr 23, 2013 at 12:40 AM
-- Server version: 5.5.24-log
-- PHP Version: 5.3.13

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
-- Database: `inclasscms`
--

-- --------------------------------------------------------

--
-- Table structure for table `event`
--

CREATE TABLE IF NOT EXISTS `event` (
`event_id` int(25) NOT NULL AUTO_INCREMENT,
`event_title` varchar(25) NOT NULL,
`event_location` varchar(25) NOT NULL,
`event_date` date NOT NULL,
`event_posted_date` date NOT NULL,
`event_cost` decimal(10,0) NOT NULL,
`event_contact` varchar(25) NOT NULL,
`event_contact_email` varchar(25) NOT NULL,
`event_description` text NOT NULL,
PRIMARY KEY (`event_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

--
-- Dumping data for table `event`
--

INSERT INTO `event` (`event_id`, `event_title`, `event_location`, `event_date`, `event_posted_date`, `event_cost`, `event_contact`, `event_contact_email`, `event_description`) VALUES
(1, 'smithWedding', 'johnston', '2013-04-20', '2013-03-20', '20000', 'rhonda', 'rhondasmith@hotmail.com', 'Rush wedding'),
(2, 'viengGraduation', 'desMoines', '2013-04-24', '2013-01-01', '15000', 'kim', 'kimVieng', 'Asian event'),
(3, 'briadalShower', 'grimes', '2013-05-08', '2013-03-13', '10000', 'sarah', 'sarahh@gmail.com', 'conservative bridal shower'),
(4, 'retirement', 'urbandale', '2013-04-12', '2013-03-12', '5000', 'harry', 'harry@gmail.com', 'suprise');

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
10-Jun-13 09:56
I would like to know how you would write this for multiple tables
21-Jun-13 17:24
I am getting this on the index.php page.

"Sorry, a problem occurred. Please try later."

Then I downloaded the source code and again I got the same error.

Can you please help me out here.

I am using LAMP.

Thanks
22-Jun-13 11:00
Hi again all, I have been going thru MANY MANY updates and converted the development branch to the "master" branch. https://github.com/geraldbullard/gnscms/archive/master.zip

for all who are interested in the gnscms please download from the master branch from now on and post any issues to the "Issues" page for gnscms ( https://github.com/geraldbullard/gnscms/issues/new ), if not directly related to the original code for "cms in an afternoon"

--
Gerald B
http://3g-dev.com/
23-Jun-13 18:29
This article is one of the worst I have ever seen...ever! I am not just saying that, check out the demo versus the download code for admin.php. Its reidiculous, and no ideas how to change passwords or username in admin.php, for beginners? rubbish!
23-Jun-13 18:33
Will someone ever post a real simple "How create a simple CMS" article. albeit she did mention that people are using different servers, have to give her that, but how to configure this monolith step by step she didnt include.
23-Jun-13 22:44
Hmmm, lets see.... if I were to give away free food to hungry people, do you think they ( idiot_asleep ) would complain that it didn't meet their taste expectations?

Yet the free code this article provides could be considered one and the same to "hungry" developers seeking more knowledge and skill. not to mention the time involved in not only writing the code, but documenting the method to recreate a system for one's own needs... gnsCMS for one.

Sorry to reply with what may seem to be a personal attack, but it simply gripes me to see ANYONE so easily disrespect the generosity of others in an effort to assist those of less skill and knowledge and give of their time so freely.

And for the record this article was not intended to be a FULL explanation of how to develop and implement an all encompassing CMS system, merely a very simple base to build upon.

WERD!

[Edited by geraldbullard on 23-Jun-13 22:45]

--
Gerald B
http://3g-dev.com/
23-Jun-13 23:11
I completely agree. This is the best and most helpful of all the tutorials I have found online. The code is a great starting point to a great CMS. The tutorial is well produced.
07-Jul-13 17:50
Hi, great tutorial.

Unfortunately after completing it though I can't seem to get the system to load properly. I copy-pasted my own code from the site and also downloaded the code with the same results.

Using Firefox/iceweasal to go to http://localhost/cms just displays a small section of index.php -


title . " | Widget News"; require( TEMPLATE_PATH . "/viewArticle.php" );
} function homepage() { $results = array(); $data = Article::getList( HOMEPAGE_NUM_ARTICLES ); $results['articles'] = $data['results']; $results['totalRows'] = $data['totalRows']; $results['pageTitle'] = "Widget News"; require( TEMPLATE_PATH . "/homepage.php" ); } ?>


while Chromium just displays the entire content of index.php

I feel like there must just be some simple step I am forgetting, but I don't know what it is. Do I have something configured wrong with the LAMP server?

SOLVED ---- I JUST WENT BACK THROUGH THE DEBIAN LAMP SETUP STEPS AND IT SOLVED IT. THANKS!

[Edited by ross on 07-Jul-13 19:42]
24-Jul-13 17:40
Please, heeeeeeeelp!

I've tested locally with Mamp... Works well

But when you upload it to a server outside, it doesn't work at all... Is not anything with the database, because it connects, but it seems that lost connection or something, because it simply doesn´t fetch data from the database, I tested with the original source code and nothing.

Please.
02-Aug-13 05:40
Hello there!

I have adjusted a few settings, instead of Article class , I have chaged it to House and houses.

Now : Editing works fine, and the content gets updated, but adding new content does not work, I enter all the information, get the Message that my changes have been saved, but nothing get added.


Any idea what it could be?
Kind regards,
Dom

[Edited by DisturbedGoW on 02-Aug-13 05:47]
13-Aug-13 00:02
Thanks for all the kind words on this tutorial - I'm really happy that it is helping so many people.

@Ngelltran and @DisturbedGoW: Did you look in your server error log to see if there's a database exception in there?

Matt

--
Matt Doyle, Elated
24-Aug-13 03:10
Hi,accomplishments for the job, clearexplanation.I installed the cms easly.Can I add a dynamic menu with Articles?
I would like to add menu items that link to articles.
Best regards,
Roberto
01-Sep-13 02:04
Hello All...!

It was working fine to me until i change WAMP to a new version. Dates became wrong showing "31 DEC 1969" on all posts.

Database shows me correct dates, but on HomePage and AdministrationPage shows me incorrect dates (31 DEC 1969).

I didnt change anything in the code, only changed WAMP version.

Could you help me?

Thank You.

P.S.: My DB has 2 diferent dates on same table: publishingDate and closingDate and only one has the problem. Below i show where i believe is the problem:

public function storeFormValues ( $params ) {

// Store all the parameters
$this->__construct( $params );

// Parse and store the publication date
if ( isset($params['publicationDate']) ) {
$publicationDate = explode ( '-', $params['publicationDate'] );

if ( count($publicationDate) == 3 ) {
list ( $y, $m, $d ) = $publicationDate;
$this->publicationDate = mktime ( 0, 0, 0, $m, $d, $y );
}
}

if ( isset($params['closingDate']) ) {
$closingDate = explode ( '-', $params['closingDate'] );

if ( count($closingDate) == 3 ) {
list ( $y, $m, $d ) = $closingDate;
$this->closingDate = mktime ( 0, 0, 0, $m, $d, $y );
}
}
}

[Edited by Marki on 02-Sep-13 23:40]
26-Sep-13 08:53
Hello
Can someone explain to me how the code handles the control of the form. When you click on the button and you did not complete the fields as for example, the field is red and indicates. I'm french and it must be the browser that runs because the error is in french and said Please complete the fields.
I searched but did not find any function that
Thank you in advance
26-Sep-13 08:54
Hello
Can someone explain to me how the code handles the control of the form. When you click on the button and you did not complete the fields as for example, the field is red and indicates. I'm french and it must be the browser that runs because the error is in french and said Please complete the fields.
I searched but did not find any function that
Thank you in advance
27-Sep-13 03:08
I found ...
It should simply add the required input:
<input type="date" name="myDate" title="Date" value=" "required>
Works with every browser except safari
14-Oct-13 17:25
Please help. I'm using MAMP. When I go to my localhost, select cms I get a blank screen. Can anyone help me with whatever I did wrong.
And thank you for the tutorial. It was wonderful.
19-Nov-13 16:49
Hello,

I only whant to say this is a Great article, its workin fine.

Greetings

--
If its not fun, youre not doing it right
21-Nov-13 03:24
Hello, congratulations for the article.
How can I integrate pagination in PHP in the article list ?

Thanks.
21-Nov-13 22:15
Hi All,

i have 2 dates in the same table, how can i manage "storeFormValues in class Article" to work with this 2 dates?

publicationDate

closingDate

Thanks.
-----------------------------------
Resolved my problem adding UNIX_TIMESTAMP(closingDate) statement at function getList in Article class.

[Edited by Marki on 22-Nov-13 10:15]
26-Nov-13 04:05
This article is very helpful at all, I am as new to learn web programming very helpful at all. Thank you very much ..

--
http://kliknans.com/
29-Nov-13 09:17
Hello... Hopefully this isn't too late.
I have done the entire article, the add new article works on my server, and is saving the article data to the database, but none of the articles are showing up either in the list on the admin side, nor on the homepage.

I'm not sure what I missed, or if anyone has had this issue, but it seems to be the only part of this script that doesn't work for me.

Anyone with any idea what I missed?

Thanks
29-Nov-13 09:17
Hello... Hopefully this isn't too late.
I have done the entire article, the add new article works on my server, and is saving the article data to the database, but none of the articles are showing up either in the list on the admin side, nor on the homepage.

I'm not sure what I missed, or if anyone has had this issue, but it seems to be the only part of this script that doesn't work for me.

Anyone with any idea what I missed?

Thanks
01-Dec-13 10:26
Interesting post! I have a problem when typing in cyrillic - it does not insert any data in the table, or inserts only numbers instead of letters. I added <meta charset=utf-8"> in header.php but no result! Could you help me?

Also it would be great if there is a possibility to add or remove images in the posts

Thank you in advance!
Best Regards, me
09-Dec-13 09:36
Hi,

I found this article very helpful and I have managed to build website based on 80% on it, but my problem is in servers that are not supporting PDO.

Is there any way to rewrite this code and use it without PDO?

Thanks in advance.
15-Dec-13 17:53
First of all great tutorial! thanks so much.

@matt - are you stilll planing to make a pagination tutorial? It would be the greatest.

@chotikarn - I was trying to implement your code for pagination, but i get some problems about some undefined index and variables, do you maybe have time to help me with it?

[Edited by legarth on 15-Dec-13 17:54]
11-Jan-14 14:53
Hello All!

Awesome tutorial, extremely approachable and informative!

I am trying to develop little site, wchic is non-english. Could you please help me on how to change publication date from being displayed like "Published on 11 January 2014" to "Published on 11-01-2014"?

Thanks a lot!
All the best in the New Year!
17-Jan-14 16:44
Thanks for this wonderful tutorial but i've been trying to implement pagination in the archive.php and listarticles.php but i've not been able to acheive this....pls can you write a follow up tutorial on pagination or can anyone help.....Thanks

--
dan
17-Jan-14 23:51
I put the code from the homepage.php that shows the last 5 articles in to a section_footer.php include file.
When I click on the link to view the article it takes me to the viewarticle.php but I get a "undefined index" message in the include section footer.
When I go to the article archives it doesn't do this.
Any ideas how to correct this would be helpful.
Thanks
12-Feb-14 08:11
I enjoyed the tutorials it work good!! I have a question...
If i want to duplicate the edit form for another similar usage for example a slideshow with articles in the same homepage what is the better way ??
12-Feb-14 08:35
@smartin1970
problem when you want to add new article
open Article.php
find $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
replace $conn = new PDO( DB_DSN, DB_USER_NAME, DB_PASSWORD );

@malpikrol
open listArticles.php
find
<?php echo date('j M Y', $article->publicationDate)?>
replace
<?php echo date('d-m-Y', $article->publicationDate)?>

[Edited by pedja82 on 12-Feb-14 08:40]

--
http://www.optimizacijasajtaseo.net
12-Mar-14 15:21
Hi,

Im hoping someone can point me in the right direction for this. I am having a few difficulties moving around the index.php file.

I basically wanted the index.php file to become a news page on my site but i dont want the user to see in the browser URL that it is aimed in the cms/ directory.

So i moved the file out and got countless errors so i moved everything out(not ideal), in to the root and it works but when u click on an article it redirects back to the home page and the archive link on the index.php page.

Is there a reason for this or a better solution?
22-Mar-14 03:16
A few of us sees this:

"Sorry, a problem occurred. Please try later."

What kind of an error-message is this???
The only purpose of such a message is to obscure the cause of what's creating the error-message. The fact is, no one will ever be able to correct any fault occurring with their scripts or the server configuration.
One other thing: "Please try again later." -Is this a joke? If your car runs out of gas,-do you seriously think it helps to try again later without filling gas?

Here's the solution:
Open up config.php in any text editor and remove the following at the end of the script:


function handleException( $exception ) {
echo "Sorry, a problem occurred. Please try later.";
error_log( $exception->getMessage() );
}

set_exception_handler( 'handleException' );


Save config.php.

Now, refresh your browser window and look at the error message. If it says anything about mysql and username/password, you need to edit config.php and type in the correct database name, username and password. Save config.php and refresh the browser window. Now, everything will be OK,-or you'll get another error message that contains something with "Fatal error . . PDO blah-blah-blah in some document at line number so and so . . . "

If this happens you need to uncomment a couple of extensions inside the php.ini-file, namely:
extension=php_pdo.dll and extension=php_pdo_mysql.dll
If there's a semicolon in front of any of these, the required modules to make PDO work will not be loaded, so remove the semicolons and restart your server. Refresh browser window. If you still get the same error message,-stop apache and then start apache again instead of just restarting. As an alternative you can reboot your computer.
Make sure you are editing the php.ini-file that the system is actually reading. You can make a phpinfo.php-file and run it in your browser to see where your php.ini resides and also which PDO modules are loaded. If you have a mysql-database, mysql should be listed under the PDO-section.
22-Mar-14 14:33
A few of us sees this:

"Sorry, a problem occurred. Please try later."

You are free to change the error messages to whatever you want.

But you seem to have missed the point of the article and TUTORIAL.


It is NOT for you to use as is. It is, as it says, a tutorial, so anyone can inspect the code and LEARN the programming necessary and how to handle errors for themselves.

If you want to change the language of the interface .... You can.

If you want to extend the functionality of it ..... You can.

And if you ARE using it on a production server be aware that sending detailed error messages WILL assist vandals and 'crackers' in finding what vulnerabilities may exist.

[Edited by chrishirst on 22-Mar-14 14:34]

--
Chris.
So long, and thanks for all the fish.
http://webmaster-talk.eu/
24-Mar-14 07:22
Dear Matt,
This tutorial is very helpful for me to learn PHP. I was looking for a tutorial to learn to make my own CMS. I have basic knowledge of PHP but I am learning more from your tutorial. Thanks a lot. I typed all your codes and followed your tutorial step by step. Everything is working fine except the following code:

public static function getList($numRows = 1000000, $order = "publicationDate DESC")
{
$conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
$sql = "SELECT SQL_CALC_FOUND_ROWS *, UNIX_TIMESTAMP(publicationDate) AS publicationDate FROM articles ORDER BY " . $order . " LIMIT :numRows";
$st = $conn->prepare($sql);
$st->bindValue(":numRows", $numRows, PDO::PARAM_INT);
$st->execute();
$list = array();

while($row = $st->fetch())
{
$article = new Article($row);
$list[] = $article;
echo $article->id;

}

$sql = "SELECT FOUND_ROWS() AS totalRows";
$totalRows = $conn->query($sql)->fetch();
$conn = null;
return (array("results"=>$list, "totalRows"=>$totalRows[0]));
}

i tried to click the title of the article and view the article but it doesn't take me anywhere. The URL i get is: http://localhost:122/cms/index.php?action=viewArticle&articleId=

I tried to find what is wrong in the codes and downloaded your whole code and run it. The problem is the same. I tried to go through the codes and tried to echo variables. In the code above i is not returning id of the article. Help pls

--
sud1231
11-Apr-14 01:29
I know HTML, CSS3 and how to set up and control tables in MYSQL using PHPMyadmin and the very basics of PHP but haven't quite learned how to connect MYSQL with PHP.

This looks like a good informative tutorial and it will hopefully take me to the next step in making websites.

Btw, is it really a good idéa to have admin.php and config.php in the root directory?

[Edited by pennyc on 11-Apr-14 01:58]
11-Apr-14 13:39
php files cannot be 'read' from a HTTP:// request unless the values are written to the output stream using echo() or print()

--
Chris.
So long, and thanks for all the fish.
http://webmaster-talk.eu/
12-Apr-14 12:46
Pagination !

Has anyone successfully done this that can assist me?

if not, Hi Matt,

Pagination seems to be a wanted thing around here people want and I have been trying to get it working on my site for quite some time without any luck can you please create a tutorial for integrating this in to this CMS.

I have tried Chokitarns example but i get quite a few errors and had no luck fixing them.

any help is much appreciated as i need this working before i can go live.

Many Thanks,
Martin
14-Apr-14 15:30
Is it just me or is the Form for article missing? I've gone through the entire code and can't figure out how to create a new article? Can't find any Form for it anywhere?
29-May-14 06:50
Hi, are you sure this works correctly?

if ( !isset($_GET["articleId"]) || !$_GET["articleId"] ) {
homepage();
return;
}

when i write non-existing id into url, it shows me an error instead of homepage.

thanks a lot.
29-May-14 17:04
That code does not check if an ID is valid and then deliver the appropriate article, it only checks if the key and A value is in the form associative array, and if either POST or GET is true it calls the homepage() function and THAT will serve the article ... IF it exists, .... If it doesn't, ..... you get a HTTP 404 error.

--
Chris.
So long, and thanks for all the fish.
http://webmaster-talk.eu/
27-Jul-14 09:53
This setup works great. All i did was open 'config.php' and revise the DB_USERNAME and DB_PASSWORD. If you are using a localhost setup (XAMPP or WAMP) just revise DB_USERNAME to "root" and DB_PASSWORD to "" (unless you initiated a password.
27-Jul-14 10:57
If your CMS is accessible from the outside world ie; The Internet. Absolutely do NOT, EVER use the root user and password for database communication.
The root user has ALL privileges allowed so if anyone does try cracking your system they can delete everything.

--
Chris.
So long, and thanks for all the fish.
http://webmaster-talk.eu/
06-Oct-14 09:47