I'm working on revamping my CMS right now. Currently, I'm trying to minimize the front end code to make theming easier. To display the latest posts, this is the code I am using:
<?php
$query = mysql_query("SELECT * FROM posts order by id desc") or die(mysql_error());
while($row = mysql_fetch_array($query)) :
?>
<h3><?php echo $row['title'] ?></h3>
<?php endwhile; ?>
What would be the best way to simplify this for the front end user? I'm thinking about using a functions.php file but I not sure exactly how to do that. Is there a way I could make the first two lines of php into a function and then the user would only have to call the function?
Typically you use two layers.
Database access layer: Query function accepts arbitrary queries, verifies return value, logs to file on error, dies if needed. You can create separate functions for querying+retrieving data in one step (query_one_row(), query_dataset_as_array(), ...).
Data model layer: Separate functions for each major query, each calling the lower layer. eg: get_recent_posts(),
Try to rewrite #Sascha's answer to use these two layers.
Here is the function you could use:
function getPosts() {
$query = mysql_query("SELECT * FROM posts order by id desc") or die(mysql_error());
$result = array();
while($row = mysql_fetch_object($query)) {
$result[] = $row;
}
return $result;
}
and in the template:
<?php foreach(getPosts() as $post) : ?>
<h3><?php echo $row->title ?></h3>
<?php endforeach; ?>
note: i know I'm not answering your question, but just wanted to give you a heads up.
you might want to split the different concerns of the code. on one hand there is the render of the data, on the other hand, the business logic and the persistance layer. it seems you're coding everything in one file and this may make matters complex in the future. try using an mvc like yii, zend framework, or symfony2.
also, the "or die" is pretty much a bad practice. notice how you are loosing the chance of logging the error properly and outputing the error directly to the user instead of giving them a nice error page to look at, and maybe give you some feedback about the error.
edit: for the persistance layer, you could try doctrine2
To improve a little on Sascha's answer above, you could do this...
<?php
foreach(getPosts() as $post)
{
printf( '<h3>%s</h3>', $post->id, $row->title );
}
?>
Works exactly the same, but a bit easier to read, imo.
Related
I posted in a previous question how to get my rating script to work. I have now finally got it to work using maths rather than the avg function but i still have two questions to ask.
Q1) Is there a better way of displaying my results other than using echo all the time
Q2) How do i add in my other three performance values in to this script they are all in the same table
<?php
mysql_connect("localhost", "username", "password") or die ("sorry we could not connect to our servers");
mysql_select_db("db") or die ("sorry we could not our database");
$find_data = mysql_query("SELECT * FROM rating");
while($row = mysql_fetch_assoc($find_data))
{
$id = $row['id'];
$current_rating = $row['Reliability_timekeeping'];
$reviews = $row['reviews'];
$new_rating = $current_rating / $reviews;
echo "($reviews Reviews)";
echo "Reliability & timekeeping: ";
echo round($new_rating,1);
echo "/10";
}
?>
sorry for my writing skill writing is not my strong point and still new to php
You can use a template engine that fills your data in to a template that you can write like HTML with some additional placeholders. A template engine has some great advantages over echoing out the values:
separate code from layout
reusable
better maintainability and readability
Here are some of the template engines I used in PHP, they also have good documentation to get you started:
Smarty
Twig
To avoid using echo all the time, you can just accumulate all the output in a variable and use a single echo. As a good practice, in my scripts I try to use just one echo at the script end. This will make each page a few mili-seconds faster, as less PHP / web server interactions will be necessary:
$Response = "";
$Response .= "($reviews Reviews)".
"Reliability & timekeeping: ".round($new_rating,1)."/10";
...
more code
...
echo $Response;
Just indent and break lines in a way that the code gets readable, and everything will be fine.
so. i've been trying to update the password. randomly generated. but. if i refresh the database, nothing happens. what's wrong with my code?
this is my controller:
function create_password()
{
$this->load->model('members_model');
$newRow = array(
'name' => $this->input->post($a);
'value' =>
);
$this->membership_model->passchange($newRow);
}
this is my model:
function passchange()
{
$this->db->select();
$this->db->from('membership');
$this->db->where('security_answer',$this->session->userdata('security_answer'));
$q=$this->db->get();
if($q->num_rows() > 0) {
$data = array();
foreach($q->result() as $row) {
$data['result']=$row;
$this->db->where('email_address', $this->session->userdata('email_address'));
$this->db->update('membership', 'password');
}
return $data;
}
}
and this is my view:
<?php echo form_open('login/create_password')?>
<?php $this->load->view('includes/header');
$CI =& get_instance();
$CI->load->model('membership_model');
$result = $CI->membership_model->passchange();
foreach($result as $row) {
}
?>
Your Email Address is: <?php echo $row->email_address;?> <br/>
<?php
$a = random_string('alnum', 6);
?>
Your password is: <?php echo $a; "<br/>"?>
<p align="right"><?php echo anchor('login/signin', 'Back to Login Page'); ?></p>
the password in my database is blank. it is not updating. please help. thank you in advance! :)
Marishka you really really need to watch those tutorials I gave you before continuing this process. You're going to get to a point where your application is so badly messed up it will be nearly impossible to fix.
Almost everything you're doing there shows bad practices, not the least of which is stop loading the CI instances and getting data from the model in the view.
Here are the problems with your code as it stands.
You're creating an array of $newRow using a post value you're not getting because you aren't posting anything. Creating a variable in a view does not automatically post it back, to post data to a controller it needs to be in a form and that form needs to have an action to call the controller function.
$a isn't going to equal anything because random_string isn't a php function that I know of, it looks like something you just pulled out of the middle of a tutorial without reading how it was created, so $a is going to be null, even if it were posted back to the controller it would still have no value to insert into the database.
In your model that you're passing the $newRow to you're never actually getting the $newRow into the function.
This has nothing to do with it not working but you're basing which record to update on the security answer? The possibility of numerous users having the same answer makes this a horrendous idea.
As was previously said the second parameter in active records update function should be an array. So to understand what that function is doing it breaks down like this.
$this->db->update ($tableToUpdate, $arrayOfValuesToUpdate);
The array of values are key pairs so for password you'd have an array like the following:
$arrayOfValuesToUpdate = array(
'nameOfPasswordFieldInYourDB' => 'value you want to set the password to'
);
I really get the feeling you're trying to learn CI from various examples and tutorials and you really do need to just stop and look at the nettuts tutorials I linked you before from step one. Your practices are terrible and your understanding of what you're actually doing is low enough that you're just copying and pasting and not getting what it is that's supposed to actually be happening. The Nettuts tutorials will give you that base understanding you need to do these things properly.
The error lies here
$this->db->update('membership', 'password');
This method gets array as second parameter
$data['password'] = $newpassword;
$this->db->update('membership', $data);
Also use this method
echo $this->db->last_query();
to see what query has been run recently. And dont forget to use where instruction with update instruction. Read the userguide again it is very helpful
https://www.codeigniter.com/userguide2/database/active_record.html
Alright so I have no idea how to even begin doing this
But basically I have one of the menus that displays on every page come getting it's text and links from a mysql database.
Here's the code:
<table class="LeftMenuTable">
<?php
// Generates the left menu from the LeftMenu_items table
$result = MySqlQuery("SELECT * FROM Menu_LeftMenu;");
while ($row = mysqli_fetch_assoc($result))
{
if ((int)$row['header'] == 0)
{
// echos value is on or not
echo "<tr><td class='LeftMenu'><a href='" . $row['url'] . "'>" . $row['text'] . "</a></td></tr>";
}
else if ((int)$row['header'] == 1)
{
// header
echo "<tr><td style='border:0px; height:5px;'></td></tr>"; // adds extra empty tabel
echo "<tr><td class='LeftMenuHeader'><b><strong>" . $row['text'] . "</strong></b></td></tr>";
}
}
?>
</table>
function MySqlQuery($Query)
{
$result = $mysqli->query($Query) or die(ReportMysqlError(mysqli_error($mysqli), $Query));
return $result;
}
I feel like any sql queries that could be be replaced by html cache somehow are reducing the site's speed.
If anyone has any information or suggestions it's much appereciated.
If you were keen enough, I would suggest a slightly different approach.
If you make your pages using a templating language called "Smarty" find out more here. http://smarty.net you should find that smarty will manage the caching for you.
How is this related to your question.
It will make your web development easier as you will stop "echoing" content into your HTML.
Smarty will do the caching for you. When a smarty template loads, smarty keeps a copy of it (or you can tell it cache a file for x hours, days etc).
As you site grows smartys caching will help keep your site running and loading fast.
You have to very little work to make caching work, just use smarty templates to build your site.
Lastly you may find it a LOT simpler to build sites using smarty.
John.
In the method that calls your database (to fetch menu items and build the corresponding html):
Check if there is an item in the current $_SESSION with the html of your menu.
If (1) returns nothing, execute the query, build the html and store the results in $_SESSION.
Return the html of your menu.
A bit more information about how you can use the session can be found here.
This way, your menu query will only be fired once per session. I doubt it's a real performance breaker though (if your query is more or less in normal form).
Note that changes in your menu will not get picked up automatically before the session expires with the mechanism described above.
I usually use memcached (or some other similar solution) when I need to organize a caching layer.
But in your case may be it'd be done in a more simple way: use an intermediate 'generator' script which will be fired each time the table in question is updated (as it's updated from some form of admin panel, right?) and will generate a static file, then include this file within your main view script.
I am trying to call pages using Zend_Paginate() on a query that loads based on a GET search string the query essentially does the following:
SELECT * FROM table WHERE column LIKE '%searchstring%' OR alt_column LIKE '%searchstring%';
The query works fine when called via search/submit text form and the URL returns something similar to
URLINK.php?search=searchstring
However when trying to move onto the next page the program dumps me back to the paginate alternate URL (used for errors or no page display)-- hope this last line makes sense it is late and am doing my best to type this up with transparency.
What is the best method when using paginate against URL.php?search=searchstring"?
A bit more on the call to the url
//search query
$search = searchQuery('search', 'list_sql_rows.php');
$results - searchTable($dbRead, $search);
search method using the variables above in the order below
if(isset($_POST['submit_search'])) { $searchstring = $_POST['searchstring'];
if($searchstring) { header('Location: results.php?search=' . $searchstring); } }
This bit works well, but when I try to call the results.php?page=2 with paginator the system reverts me to the fall back URL list_sql_rows.php as mentioned above. Any thoughts/comments are appreciated.
Just to clarify a search field/form from the search.php page sends the $searchstring to the results.php page via $_POST && $_GET as fail safe. The get method sends the $searchstring in the URL header so the results of the search DO work on the first page results.php?search=$searchstring. This works just fine. The pagination seems to lose the $searchstring, and I wonder if this is due to a loss of the $_POST/$_GET when paginator begins to 'paginate' it returns URL results.php?page=2 so it seems $_GET may not be the method of choice?
UPDATE
On the write track now paginate works it is my link structure that is broken.
_results_samples.php?search=robert&page=4_ will in fact return page 4 of the paginated results using the word ROBERT
SOLUTION FOUND VIA variant suggestion by ROCKYFORD
variant of recommended method by first persisting $searchstring
change to paginate links as shown below
<a href='" . $_SERVER['PHP_SELF'] . "?search=" . $searchstring . "&page={$page}'>$page</a>
Here is the example of correct using of pagination:
in action-method:
$select = $clients->getAll();
$paginator = new Zend_Paginator(new Zend_Paginator_Adapter_DbSelect($select));
$paginator->setCurrentPageNumber($this->_getParam('page'));
$paginator->setItemCountPerPage(20);
$this->view->clients = $paginator;
in a view script:
<?php if (count($this->clients) > 0): ?>
...
<?php echo $this->paginationControl($this->clients, 'Sliding', 'partials/paginator.phtml'); ?>
<?php else: ?>
<h3 class="notice">No registered clients found!</h3>
<?php endif; ?>
But even if you will fail with this variant, you can always try to compose your own component, Zend only aids us in solving some tasks.
you need to make sure you preserve the query strings between requests, use Zend_Session_Namespace or Zend_registry.
Everytime Zend_Paginator loads a page when using the DbTableSelect or DbSelect adapters it has to hit the db with the query, it just changes the limit option.
Or you could just dump the whole query result into a Zend_Paginator_Adapter_Array and it will page through the array.
[edit]
you are going to have to persist the query string between requests someway so you can put it back in the url string, I usually use Zend_Registry, but then I use the whole MVC stack. You don't seem to be using the whole stack so you'll need another method, probably $_SESSION would work. I'm sure there are many other ways to persist this data.
P.S. you didn't mention which adapter you are using so I'm making some assumptions.
[edit]
Personally I always use $_post for this when possible to avoid all this, only seem to have this problem with $_get.
i have this process that is the heart of my app, that im creating, but for some reason i feel like its the worst way to do it(instinct) , and i wanted to see if thier is something wrong with this process, and am i approaching it in a bad way! p.s. the code works fine, just refactoring problem.
the process is:
users go to homepage, they see thier latest activities, by other site memebers(home.php),
//function to bring the latest activities from database
$results=function getUserUpdates($_SESSION['user_id'];
while($row = mysql_fetch_array($results))
{
//another function to format the activities in a social stream
echo formatUpdate($row['user_note'],$row['dt'],$row['picture'],$row['username'],$row['id'],$row['reply_id'],$row['reply_name'],$row['votes_up'],$row['votes_down']);
}
i have put the function codes in pastie.
formatUpdate function http://pastie.org/1213958
getUserUpdates function http://pastie.org/1213962
EDIT both functions are from different files they are included in home.php,
formatUpdate from functions.php
getUserUpdates from queries.php
First of all, it's good that you have separate functions for getting the data and for formatting the data. It's a good start toward refactoring your code. It makes it easier in the future: if you ever want to format your data differently, you can just expand your formatter.
Second, this is what coreyward meant by a lambda:
$results=function getUserUpdates($_SESSION['user_id'];
Remove the function keyword. You use function when you're defining a function. But here you're only calling one. (You defined it in queries.php.)
Third, I agree with webbiedave about the echo statements. A good way to avoid that: In the "heart" of your app, collect all the HTML into one place. Then, when you've collected everything you're going to display on the page, you can echo it all at once. This makes it a lot easier to keep track of what you're doing, and to remember the order of everything. It also makes it easier to add headers and footers, or do more formatting. Otherwise, if you have echo statements scattered around your code, it's a lot easier to let something slip that shouldn't be there.
Here's a very basic example of what I mean:
$html = '';
$results = getUserUpdates($_SESSION['user_id'];
while($row = mysql_fetch_array($results)) {
$fields = array(
'user_note' => $row['user_note'],
'dt' => $row['dt'],
'picture' => $row['picture'],
'username' => $row['username'],
'id' => $row['id'],
'reply_id' => $row['reply_id'],
'reply_name' => $row['reply_name'],
'votes_up' => $row['votes_up'],
'votes_down' => $row['votes_down'],
);
$html .= formatUpdate($fields);
}
// This way you can do whatever you want to $html here.
echo $html;
Also notice that I put all the fields from $row into an array and passed it to formatUpdate(). That has two advantages:
It's easier to read.
If you ever
want to change the fields that
formatUpdate deals with, you don't
have to worry about searching
through your code to change the
arguments every time you call it.
Firstly, I think you mean:
$results = getUserUpdates($_SESSION['user_id']);
In your getUserUpdates() function there is a redundant branch:
if ($username == $_SESSION['u_name']){
// return something
}
if ($username != $_SESSION['u_name']){
// return something else
}
You don't need the second if statement as any code run at that point will only be run if $username != $_SESSION['u_name'].
In my opinion, it's usually better not to have different functions directly echoing HTML up the stack (such as echoVote()). It's preferred to have functions return data and have the original caller echo it. This allows the caller to perform additional data massaging if desired.
Other than that, your code is fetching data, looping through and acting on the results which is pretty much standard fare.
I think your instinct is to be a little too harsh on yourself ;) There are improvements to be made but it's certainly not the worst way to do anything.