Make post archives with pure PHP and yii? - php

I would need to create archives listing ( much the same functionality as the ones in WP websites ), but with using PHP and Yii framework. Since i've been thinking about how I could accomplish this a lot and didn't come up with anything useful, i'm asking your help here.
So for example, mysql table would look something like this:
Columns:
id (int AI, primary )
title ( varchar )
content ( text )
creation_date ( timestamp )
How could I use the timestamp column value, to select only the posts in distinct months posted ( so that I can determine which months I need to list as links to the respective archive page which will list all the posts posted under that month ) ?
Btw, only helping me on how to do it with PHP is enough, you don't have to go through the hussle of making the code work with Yii since, obviously it is not possible, because you dont have controllers, models etc. :)

Gj to whoever voted down my question, you were realy helpful. I guess haters exist even on these kinds of websites, which is sad. Anyways ,enough about them, here is something I came up with today by learning new MySQL function, which I didn't know existed before :)
You can just use MySQL DATE_FORMAT(date_column,'%format') to select the desired month, year, day, or any other "part" of the date, even though if the date is in unix timestamp. This is a simple code I came up with after a bit of fiddling around.
$query = "SELECT DISTINCT DATE_FORMAT(creation_date,'%M') as creation_month, DATE_FORMAT(creation_date,'%Y') as creation_year FROM posts";
$result = $connection->query($query);
if($result) {
while($row = $result->fetch_assoc()) {
$archiveArray[] = $row;
}
print_r($archiveArray);
echo '<h3>Our Archives by month</h3>';
echo '<ul>';?>
<?php foreach($archiveArray as $archiveRecord) : ?>
<li>
<?php echo $archiveRecord['creation_month'] . ' ' . $archiveRecord['creation_year']; ?>
</li>
<?php endforeach;
echo '</ul>';
}
What this code does is it "reads" the timestamp in the "creation_date" column from the DB, puts it inside the desired "format" which is specified by %M and %Y ( similar to PHP date() function formating) and assigned to immaginary column names on the fly called craetion_month and creation_year. Note the DISTINCT select, since I don't want months to repeat themselves for each post under that particular month. After that we just list them as anchors in an unordered list. This was the main problem, the rest is easy to do :)

Related

age calculation & if inside if not working / php

I am trying to convert three separate database columns into a date (day,month,year) and calculate the age so only users over the age of 15 or 18 can purchase certain products. The code below doesnt work as it echoes '0 days, 0 months, 0 years' and still adds the product to the basket. Which means the age calculation doesnt work, and my first if statement doesnt work either.
<?php
$username = $_SESSION['solentuser'];
echo "$username's account!<br>";
$conn = new PDO("mysql:host=localhost;dbname=u;","u","p");
$productID= htmlentities($_GET['ID']);
//startdate
$result=$conn->prepare("SELECT * FROM users WHERE username=:username");
$result->bindParam(":username",$username);
$result->execute();
$row=$result->fetch();
$birthdate = $row['yearofbirth'] . $row['monthofbirth'] . $row['dayofbirth'];
$presentdate = date('Ymd');
$birthday = new DateTime($birthdate);
$currentdate = new DateTime($presentdate);
$age = $birthday->diff($currentdate);
echo $age->format('<br>%d Days %m Months %y Years<br>');
//enddate
$results=$conn->prepare("SELECT * FROM products where ID=:productID");
$results->bindParam(":productID",$productID);
$results->execute();
$row=$results->fetch();
if($row['agelimit'] <= $age){
if($row['stocklevel'] >= 1){
$result=$conn->prepare("INSERT INTO basket(productID,username,qty) values(:productID,:username,1)");
$result->bindParam(":productID",$productID);
$result->bindParam(":username",$username);
$result->execute();
$result=$conn->prepare("UPDATE products SET stocklevel=stocklevel-1 WHERE ID=:productID");
$result->bindParam(":productID",$productID);
$result->execute();
echo "You have successfully added this product to your basket!";
}
else{
echo "This product is out of stock!";
}
}
else{
echo "You are not old enough to purchase this product!";
}
//print_r($conn->errorInfo());
?>
any suggestions as to where the error is? i have read that it is possible to write an if statement inside an if statement, so why does this one not work?
thank you!
I'd echo out $birthdate and verify there's a valid date there. (We aren't getting back single digits, a date of 2009-05-04 getting represented as '2009', '5' and '4' such that when we concatenate them, we get 200954, or maybe extra spaces. (We're not seeing the datatypes of the three separate columns.)
We might try adding some delimiters in there, so we'd get 2009-5-4, likely we could get that converted into a DateTime, using the correct format string.
If I had separate values for month, day and year, I would use PHP mktime, and then create a DateTime object from that.
(MySQL does provide a DATE datatype that allows for a very large range of valid dates, and doesn't allow invalid dates to be stored. Storing three separate columns to represent a single date just smells like the wrong way to do it. (If I actually needed the separate month and day columns (to allow indexing for some queries), I would add those in addition to the birthdate DATE column, not in place of it, with triggers to keep the values in sync with the birthdate column.)
Also, $age is a DateInterval object. You seem to be aware that we can use the format method to extract integer number of years.
$age_yrs = $age->format('%y');
We're guessing that the database column age_limit is integer years.
if( $row['agelimit'] <= $age_yrs ) {
Right before that if statement, we can confirm that what we think to be true is actually true...
echo " age_yrs=" . $age_yrs;
echo " row_age_limit=" . $row['age_limit'];
Looking closely at the debugging output helps us identify if the problem is before the if statement or after, so we aren't chasing down a problem in a section of code where there isn't a problem, the problem is somewhere else, on a preceding line.
I encourage you to develop the skills needed to debug programs that you write. It seems like you are making some (wrong) assumptions about what the variables are containing.
Adding echo and var_dump during development is a first step in verifying that what you think to be true is actually true.
I'd go as far as recommending that you look at every line of code you write as possibly going wrong, especially in edge cases.
https://ericlippert.com/2014/03/05/how-to-debug-small-programs/
(StackOverflow is a question/answer community, not a debugging service.)

Multiple MYSQL Statements executed as a single statement

I've got a bit of a problem with my code. I'm sure that it is something simple, but I just can't figure it out! I have been on tons of forums and have read several books... but every answer that I have worked to has failed. I almost guarantee that it's the way that I am using my syntax (and yes I know... procedural PHP is not really used anymore) but I am really a bit of a newbie to this and I am just trying to pick up the basics before moving onto OOP and PDO connections.
Could you please help me? At the moment I can get the user to select their date from the date picker and the results specifically from that date only will return... only problem is that the event is displaying the event_id as opposed to the name of the event that it relates to (1 = 5km run) for example.
Somehow I need to access the events table and pull the row that relates to that specific event_id.
I have normalized my database, and according to my tutor it looks ok. To give you an idea what it looks like - logins table (all user logins details), results table (a history of submitted events) events table (the events themselves).
On the results table the foreign keys are logins_id and the event_id. The primary key is the results_id in the results table and the only data stored here is the time and data (individual columns).
<?php // -----Stage 1. On submission of the form run the following -----//
if (isset($_POST['submit_d'])) {
$mydate = $_POST ['MyDate'];
$my = preg_replace('/[^a-zA-Z0-9]+/', ' ', $mydate);
if ($mydate) {
$result = mysql_query("SELECT * FROM logins WHERE username = '$username' LIMIT 1");
//This function will take the above query and create an array...
while($row = mysql_fetch_array($result))
{
//With the array created above, I can create variables (left) with the outputted array (right)
$logins_id3 = $row['logins_id'];
}
$sql = "SELECT * FROM results where $logins_id3 AND date = $mydate ";
/* ----- Here is the code that I want to use in conjunction with the above statement --->
$query = "SELECT logins.username,events.event,results.time,results.date,logins.age,logins.gender
FROM logins INNER JOIN results ON logins.logins_id=results.logins_id INNER JOIN events ON results.event_id=events.event_id
ORDER BY time ASC LIMIT 10";
*/
$resultz = mysql_query($sql);
if( mysql_num_rows($resultz) ) {
while ($row = mysql_fetch_array($resultz)) {
echo "<table><tr><th>Username</th><th>Event</th><th>Time (HH:MM:SS)</th><th>Date (YY/MM/DD)</th><th>Age</th><th>Gender</th>
</tr><tr><td>".$username."</td>"
."<td>".$row['event_id']."</td>"."<td>".$row['time']."</td>"." <td>".$row['date']."</td>"."<td>".$row['age']."</td>".
"<td>" $row['gender']."</td></tr></table>";
}
}
}
}
?>
The other thing I would like to do.. although this is not crucial, is to strip special characters from the input. Basically I'm using a jquery calendar picker and I want the user to be able to select their date in the 2014-05-26 format and the php to remove the - before it is submitted to the database, that way it doesn't effect the users experience but it will work with my current code.
Anyways sorry to waffle on, any help on either of these matters would be much appreciated!
Yours Sincerely:
Peter Scales.
You can use a join to get the data that relates to the event ID:
SELECT * FROM results r LEFT JOIN events e ON r.event_id = e.event_id WHERE ...
You can then select where "e.event_id = $event_id"; and the rest of your query logic.
You can also filter out any unwanted characters by using preg_replace: http://ar2.php.net/preg_replace

Having difficulties sorting data from mysql query using php

This code is used to get a specific list of ID's from one table, then use those ID's to get the information from another table. Once I get all the information from the 2nd table, I am attempting to sort the data alphabetically based on a field in the 2nd table.
Example, I am getting the name based on a correlating ID and then want to display the entire result in alphabetical order by name (artist_name).
Here is the code I have. When I execute this without the sort(), it works fine but is not in alphabetical order. When I add the sort() in the 2nd while statement, the page looks the same but the name and other data do not display. The source code in the browser shows that the results are being accounted for but the sort must be preventing the variables or information from being displayed for some reason.
I haven't used a sort function before and I tried looking at some examples but couldn't really find something specific to my situation. Any and all help would be greatly appreciated. I have already looked at the PHP manual for sort so no need to send me a link to it ;-)
<?php $counter = 0;
$artistInfo = mysql_query("SELECT DISTINCT event_url_tbl.artist_id FROM event_url_tbl WHERE (SELECT cat_id FROM artist_tbl WHERE artist_tbl.artist_id = event_url_tbl.artist_id) = 1");
while ($aID = mysql_fetch_array($artistInfo))
{
$getArtistInfo = mysql_query("SELECT * FROM artist_tbl WHERE artist_id = '" . $aID['artist_id'] . "'");
while($artist = mysql_fetch_array($getArtistInfo))
{
sort($artist);?>
<a class="navlink" href="<?=HOST?><?=$artist['page_slug']?>/index.html">
<?=$artist['artist_name']?>
</a><br />
<?php }
}
?>
Your best bet, as a commenter mentioned, is to use an ORDER BY clause in SQL.
SELECT *
FROM artist_tbl
WHERE artist_id = XXX
ORDER BY artist_name ASC
The other commenter who suggested using PDO or mysqli is also correct, but that's a different issue.
To answer your specific question about sorting, according to the manual,
Blockquote Note: This function assigns new keys to the elements in array. It will remove any existing keys that may have been assigned, rather than just reordering the keys.
This means all of your array keys ('page_slug', 'artist_name', etc) are wiped out. So when you try to refer to them later, there is no data there.
Were you to use this method, you would want to use asort to sort an associative array.
However, you don't want to use sort here. What you're sorting is the variables for one row of data (one individual artists), not all of your artists. So if you think of each artist row as an index card full of data (name, id#, page slug, etc) all you're doing is moving those items around on the card. You're not reorganizing your card catalog.
Using an order by clause in the SQL statement (and rewriting in PDO) is your best bet.
Here is how I would rewrite it. I have to take some guesses at the SQL because I'm not 100% sure of your database structure and what you're specifically trying to accomplish, but I think this would work.
$query_str = "
SELECT
artist.name,
artist.page_slug
FROM
artist_tbl AS artist
INNER JOIN event_tbl AS event
ON event.artist_id = artist.artist_id
WHERE
artist.cat_id = 1
ORDER BY
artist.name ASC";
$db_obj = new PDO (/*Connection stuff*/);
$artists_sql = $db_obj->prepare ($query_str);
$artists_sql->execute ();
while ($artist = $artists_sql->fetch (PDO::FETCH_ASSOC)) {
$return_str .= "<a class='navlink' href='{HOST}
{$artist['page_slug']}/index.html'>
{$artist['artist_name']}</a><br/>";
}
echo $return_str;
In all honesty, I would probably create an artist class with a display_link method and use PDO's fetchObject method to instantiate the artists, but that's getting ahead of ourselves here.
For now I stuck with procedural code. I don't usually like to mix my HTML and PHP so I assign everything to a return string and echo it out at the end. But this is close to what you had, using one SQL query (in PDO - seriously worth starting to use if you're creating new code) that should give you a list of artists sorted by name and their associated page_slugs.
You could do all of this in one query:
SELECT * FROM event_url_tbl AS event
INNER JOIN artist_tbl AS artist ON event.artist_id = artist.id
ORDER BY artist.name DESC;
This cuts out a lot of the complexity/foreaches in your script. You'll end up with
Label1 (Label 1 details..) Artist1 (Artist1 details..)
Label1 (Label 1 details..) Artist2 (Artist1 details..)
Label2 (Label 2 details..) Artist3 (Artist1 details..)
Always good to bear in mind "one query is better than many". Not a concrete rule, just if it's possible to do, try to do it. Each query has overheads, and queries in loops are a warning sign.
Hopefully that helps

PHP/SQL Alternative to db calls within nested while loops

My first post, tried to be as thorough as possible, apologies in advance if I've gotten something wrong. I'm pretty novice with PHP/SQL as well so please be patient with me. I've found a couple of similar questions about loops within loops but I'm not sure the solutions apply in my case.
I have two tables, tws_workshopNames and tws_workshops. The primary key from tws_workshopNames is used as a foreign key in tws_workshops to relate the two tables. The reason I've split this into two tables is there are many cases where the same workshop name/price/description is offered on multiple dates/times.
Can't submit a screenshot but here's a simplified outline of the table design in SQL Server:
tws_workshopNames:
workshopNameID (pri)
description
price
etc.
tws_workshops:
workshopID (pri)
workshopNameID (foreign)
date
time
etc.
What I want to happen is basically this:
query tws_workshopNames table and display workshopName/price/description/etc.
for each workshopName go through the tws_workshops table and display all records that have the same workshopNameID
In other words, go through tws_workshopNames and display the first workshopName, then go through tws_workshops and display all records that are related to that workshopName, then go to next workshopName in tws_workshopNames, display all records related to that workshopName etc.
I'm able to achieve the desired result by using a while loop within a while loop wherein the outer loop does a call to tws_workshopNames and the nested loop does a call to the tws_workshops table. However I've been reading a lot about this and it's clear this is not a good approach as it results in a lot of calls to the db, but I'm having a hard time understanding any alternatives.
Desired output:
Workshop 1
price
description
date (of workshop 1)
time (of workshop 1)
...
Workshop 2
price
description
first date (of workshop 2)
first time (of workshop 2)
second date (of workshop 2)
second time (of workshop 2)
third date (of workshop 2)
third time (of workshop 2)
...
Workshop 3
price
description
date (of workshop 3)
time (of workshop 3)
...
etc.
Here is the current code that works with nested while loops:
<?php
// query workshopNames table, what types of workshops are available?
$query = mssql_init("tws_sp_workshopNames", $g_dbc);
// pull up result
$result = mssql_execute($query);
$numRows = mssql_num_rows($result);
while($row = mssql_fetch_array($result)) {
echo "<div style=\"...\">
<span class=\"sectionHeader\">" . $row['workshopName'] . "</span><br />
<span class=\"bodyText\"><strong>" . $row['price'] . "</strong></span><br />
<span class=\"bodyText\">" . $row['description'] . "</span>";
$workshopNameID = $row['workshopNameID'];
// query workshops table, what are the dates/times for each individual workshop?
$query2 = mssql_init("tws_sp_workshops", $g_dbc);
mssql_bind($query2, "#workshopNameID", $workshopNameID, SQLVARCHAR);
//pull up result
$result2 = mssql_execute($query2);
$numRows2 = mssql_num_rows($result2);
while($row2 = mssql_fetch_array($result2)) {
echo $row2[date] . " ";
echo $row2[time] . "<br />";
};
echo "</div><br />";
};
?>
The stored procedures are very simple:
tws_sp_workshopNames = "SELECT workshopNameID, workshopName, description, location, price FROM tws_workshopNames"
tws_sp_workshops = "SELECT date, time, maxTeachers, maxStudents, teachersEnrolled, studentsEnrolled FROM tws_workshops WHERE workshopNameID=#workshopNameID"
Hope that's all relatively clear, all I'm really looking for is a better way to get the same result, i.e. a solution that does not involve a db call within the loops.
Thanks in advance for any help, been a few days straight banging my head against this one...
You are correct to avoid usage of looping queries in this case (since the desired result can be achieved with just a simple JOIN in one query).
I would avoid using GROUP_CONCAT() as well because there is a character limit (by default, you can change it), plus you have to parse the data it outputs, which is kind of a pain. I would just get all the data you need by joining and get every row. Then load the data into arrays using the workshop ID as the key but leave the array open to append each of your time data as a new array:
$workshops[$workshop_name][] = $timesArray;
Then on your output you can loop, but you don't have to hit the database on each call:
foreach ($workshops as $workshop_name => $times)
{
echo $workshop_name;
foreach ($times as $time)
{
echo $time;
}
echo "<br>";
}
This is not the exact code, and as you've pointed out in your question, you want to keep/display some other information about the workshops - just play around with the array structure until you get all the data you need in a hierarchy. You can use something like http://kevin.vanzonneveld.net/techblog/article/convert_anything_to_tree_structures_in_php/ if you are trying to build a deep tree structure, but I think that's overkill for this example.
Since this is what I would call an "Intermediate Level" question, I think you should try to work through it (THIS is what makes you a good programmer, not copy/paste) using my suggestions. If you get stuck, comment and I'll help you further.
I don't see anything wrong with the way you're doing things. I suppose you could concatenate the result and then manipulate the output in your application using one query. Your query might looks something like
SELECT
n.workshopNameId,
n.price,
n.description,
GROUP_CONCAT(w.date) as dates,
GROUP_CONCAT(w.time) as times
FROM tws_workshopNames n
INNER JOIN tws_workshops w USING(workshopNameID)
GROUP BY n.workshopNameID

PHP check if MySQL table contains value

Okay so the title may be a bit misleading. What I am trying to do is add a favorite system to my site. I have one column for my favorite things and I set it up so after each item ID there is a :. How can I check the string returned from my database (1345:13456:232:524378:324) if it contains 232? If it does I would echo preRend else I would echo insert and insert that ID followed by a :. This is what I have so far:
<?php
session_start();
require_once(".conf.php");
$logged = $_SESSION['logged'];
$user = $_SESSION['user'];
$fwdfav = $_POST['id'];
$query = mysql_query("SELECT * FROM accountController WHERE user='$user'");
if ($logged == 1)
{
while ($row = mysql_fetch_array($query)) {
if ($row['fav-itms'] //This is where I got stuck. How to check if it contains a value.)
{
mysql_query("INSERT INTO accountController ('fav-itms') VALUES ('$fwdfav')");
echo 'inserted';
}
else
{
echo 'preRend';
}
}
}
else
{
echo 'nlog';
}
?>
Thank you so much! I am sure there are a lot of errors here as I am very tired.
The approach you are taking is extremely inefficient and does not take advantage of the fact that you are using a database.
(Btw... I hope this is just example code; you have a giant SQL injection vulnerability in your INSERT query.)
What I would do instead is create a second table that would look something like:
favorites (
id int(11) NOT NULL auto_increment,
user_id int(11),
fav_id int(11)
)
And have each row represent a user-favorite pair. Then you can let MySQL do the heavy lifting of figuring out whether a user has favorited something, e.g.,
SELECT COUNT(*) FROM favorites WHERE user_id = %d AND fav_id = %d;
// Substitute the actual look-up values in using prepared statements
You could also similarly quickly get the actual favorites for a user, etc.
Remember, a database is designed for the explicit purpose of storing and looking up information quickly. PHP is a general-purpose programming language. Where possible, let MySQL do the walking for you.
(This advice is general for a moderately scaled setup. If you need to handle millions of simultaneous users, far more optimization is obviously required, and conventional relational databases might not even be suitable. But I don't get the impression that's where you're at right now.)
You could explode it in array as check, like:
$yourArr = explode(":", $row['fav-itms']);
$checkFor = 232;
if(in_array($checkFor, $yourArr)) {
//it exists
}
else {
//does not exist
}
Did you mean something like this
I know this was posted a while ago but it came up when I did a search.
I have a database storing information for my portfolio, it holds locations for images.
I am working on a page to display the full view of the project. Within the page I need it to check the columns for the images and if any are empty I need it to not display anything.
This is how I've done it.
// connect, select database, query table relevant to page. I have done a query for a specific row.
if($row[columnName1]){
echo '<div> displaying value </div>';
}
if($row[columnName2]){
echo '<div> displaying value </div>';
}
what is happening, if columnName1 in selected row has a value display the value in div else nothing. then on to column 2.
if it is done like this
if(!$row[columnName1]){
//content displayed
}
and the column does not contain a value then what is in between the {} will be ran.
Works the way I needed it to, maybe this will help someone.

Categories