I'm trying to make categorized gallery for my blog. So far I've created datebase with tables: photos (photos_id, photos_gal_id, photos_link), galeries (galeries_id, galeries_title, galeries_description), and there are other tables, but not related to this problem (such as users, posts etc).
I've established connection with db through init file:
<?php
class init {
protected $db, $result;
private $rows;
public function __construct(){
$this->db = new mysqli('localhost','root','hhpass','europa');
}
public function query ($sql){
$this->result = $this->db->query($sql);
}
public function rows(){
for($x =1; $x<= $this->db->affected_rows; $x++){
$this->rows[] = $this->result->fetch_assoc();
}
return $this->rows;
}
}?>
Then I get the data from DB through:
class Galeries extends Init {
public function fetchGaleries(){
//query db
$this->query("SELECT photos_id,
photos.photos_gal_id as 'group',
GROUP_CONCAT(photos_link) as link, galeries.galeries_title, galeries.galeries_description, galeries.galeries_id
FROM photos
INNER JOIN galeries
ON galeries.galeries_id=photos.photos_gal_id
GROUP BY photos.photos_gal_id
ORDER BY galeries.galeries_id ASC");
//return
return $this->rows();
}
}
So far it works fine.. when I call this function in seperate file with:
$galeries_a = new Galeries();
$gals_x = $galeries_a->fetchGaleries();
and if I use the
foreach($gals_x as $gals_y){
echo $gals_y['group'];
}
it does fine and lists galeries(categories): 1,2,3,4. Which are the DB-s groups, as defined by query.
NOW, the problem is, how to make the links show up inside these groups (only links that belong to that group).
I know I have to make UL/LI listings in HTML, and that is not the problem, that part works, the problem is the PHP part :)
To sum, it should look like this.
1 First Gallery
Link One
Link Two etc
2 Second Gallery
Link One
Link Two etc
3 Third Gallery
Link One
Link Two etc
4 Fourth Gallery
Link One
Link Two etc
I've tried everything: while, foreach, everything, cannot get it to work properly.
Related
Maybe due to lack of sleep I have some problems with my logic.
In CodeIgniter, I need to get the last 10 posts from the DB and display them on the page.
My Controller is as follows:
public function index() {
// $data is an array containing some useless stuff like title, etc.
// Never mind.
// Skipped header & navbar view loaders;
$this->load->view('blog_page', $data);
$this->get_latest_posts(1);
}
Now the model goes:
public function get_latest_posts($i) {
// $i is a number of posts to be displayed. Now it is 10
$query = $this->db->get('posts', $i);
return $query->result();
// Any clue what to do here, cause I need an array that contains arrays of post rows;
}
I've been trying to do a foreach cycle, but it only works when using one row;
I would appreciate your help, guys!
Every answer will have a positive impact on the life of every kitten on a planet.
P.S. I removed any unnecessary stuff from my code, like loading header&footer views.
controller function
public function index() {
// $data is an array containing some useless stuff like title, etc.
// Never mind.
// Skipped header & navbar view loaders;
$this->load->view('blog_page', $data);
$data['get_latest_post'] = $this->your model name->get_latest_posts(1);
$this->load->view('your view file name',$data);
}
model function
public function get_latest_posts($i) {
$query = $this->db->get('posts', $i);
$this->db->limit(10);
}
is this fine..
I am having difficulty sorting my data results alphabetically when matching them with the User that has placed the item in their "Locker".
I have two queries; the first one searches the database for all of the items that the user placed in their 'locker', and the second query pulls the details of the item and sorts them into a list by which brand the items are.
I feel like there is a better way to do this rather than forcing the page to run the query once for each item, but am not sure the proper way to write out the mySQL in the most efficient way that works.
I think the solution would be to pull all IDs as an array, then somehow search and sort all of their associated brands in the second query.
I currently have:
//$lockerid is pulled earlier in the code based on which locker number is associated with this user
// Pull all of the items and their ids that are in this users locker
$userlockerquery= mysql_query("SELECT DISTINCT item_id FROM lockers WHERE user_id = '$profile_userid' AND locker_id ='$lockerid' ");
while($lockeritems=mysql_fetch_array($userlockerquery)){
$indi_item=$lockeritems[item_id];
$lockeritemdetails = mysql_query("SELECT DISTINCT brand FROM inventory WHERE id = '$indi_item' ");
$brands=mysql_fetch_array($lockeritemdetails );
$brandname=$brands[brand];
echo '<div>'.$brandname.'</div>';
}
Although the results do show up with all of the brands, My problem seems to be that since the query is ran once for each items id, it cannot have the list results talk to each other, and thus cannot have them ordered by ASC alphabetically, since the query is ran once per each item.
Also because of this, the DISTINCT flag does not have any effect, since it is not matching against any other results.
As an example, my results would return in divs in order of ID instead of brand, and repeating:
Nike
Puma
Puma
Converse
Rather than
Converse
Nike
Puma
Adding the ORDER BY flag to the second query did not help, so I figured I would try to ask here for some ideas. Please let me know if any other details are needed!
Maybe try something like this class. See if it will work for your needs. It's hard to check it without trying the sql queries, but provided I've written it properly, it should work.
class MyLocker
{
// Protected means that you can't use this variable outside of the functions/class
// so you can not use $myLocker->_array; It will throw an error
protected $_array;
// Construct is basically used as an auto-function. It will execute automatically
// when you create a new instance of the class so as soon as you do this:
// $myLocker = new MyLocker($_locker); you initiate the __construct
// When you label as public, you allow it to be used outside of itself
public function __construct($_array)
{
// When you set this variable, it is now open to use in all
// other functions in this class.
$this->_array = $_array;
}
// This is the method that will do everything
public function LockerContents()
{
// Loop through query. Since the $_array was set in the __construct
// it is available in this function as $this->_array
while($lockeritems = mysql_fetch_array($this->_array)){
// $brand is something we want to use in other functions but not
// outside the class so it is set here for use in the Fetch() function
$this->brand = $lockeritems['item_id'];
// We ant to use our Fetch() function to return our brand
$_brand = $this->Fetch();
// If brand available, set it to an array
if(!empty($_brand))
$array[] = $_brand;
}
if(isset($array)) {
// Sort the array
asort($array);
// Finally, we use the Display() function for the final output
$this->Display($array);
}
else { ?>
<div>Locker is empty.</div><?php
}
}
// Establish this as an in-class variable
protected $brand;
// Establish this as a public function incase we want to use it by itself
// To do so you would write $myLocker->Fetch(); outside of the class.
// Since you need $brand for this function to work, you would need to turn
// $brand from "protected" to "public" and write $myLocker->brand = 'whatever';
// before you run the $myLocker->Fetch();
public function Fetch()
{
$query = mysql_query("SELECT DISTINCT brand FROM inventory WHERE id = '".$this->brand."'");
$brands = mysql_fetch_array($query);
// Return brand
return (isset($brands['brand']))? $brands['brand']:"";
}
protected function Display($array)
{
if(is_array($array)) {
foreach($array as $object) { ?>
<div><?php echo $object; ?></div><?php
}
}
}
}
// You should be using mysqli_ or PDO for your db connections/functions.
$_locker = mysql_query("SELECT DISTINCT item_id FROM lockers WHERE user_id = '$profile_userid' AND locker_id ='$lockerid' ");
// If there are more than 0 rows, create locker.
if(mysql_num_rows($_locker) > 0) {
// Create new instance of the locker app
$myLocker = new MyLocker($_locker);
// Display the results
$myLocker->LockerContents();
}
I am involved in the development of a CMS at work using PL/SQL and an Oracle DB and I wish to replicate the same sort of structure for my own CMS using PHP and MySQL. I'm a PHP programmer from the old procedural days and i'm now trying to get to grips with OOPHP.
I have three tables. One represents a page. Another represents the templates that can be used within a page and the other represents the content. I've got as far as outputting the header and footer of the page (which are stored within the page table) however I now need to populate the page with content. To do this, I need to query the template table and assign the html code to a variable. I then need to use the content table to replace specific tags in the html code that is assigned to the variable (from the templates table) with the content from another table. So, for example:
I query the template table and pull out a column which contains a html structure. Within this structure there are self-generated tags such as [i1] [i2] [i3] which relate to columns in the content table. What I am aiming to do is replace these tags with the relevant contents of each relevant column in the content table (so [i1] would be replaced with the content from the i1 column in the relevant row. There can be multiple entries in the content table for each page so these are ordered by sequence.
I'm currently stuck at pulling an array of all content that is relevant to the specific page from the content table. I know how to do this procedurally using the old mysql interface but I can't find any recent posts as to how to do it properly in mysqli. Any tips?
Here is my current set of classes:
class Connection extends Mysqli{
public function __construct($mysqli_host,$mysqli_user,$mysqli_pass, $mysqli_db) {
parent::__construct($mysqli_host,$mysqli_user,$mysqli_pass,$mysqli_db);
$this->throwConnectionExceptionOnConnectionError();
$this->getUser();
}
private function throwConnectionExceptionOnConnectionError(){
if(!$this->connect_error){
echo "Database connection established<br/>";
}else{
//$message = sprintf('(%s) %s', $this->connect_errno, $this->connect_error);
echo "Error connecting to the database.";
throw new DatabaseException($message);
}
}
}
class DatabaseException extends Exception{
}
class Page {
public function __construct() {
if(isset($_GET['id'])){
$id = $_GET['id'];
}else{
$id = 1;
}
get_headers($id);
get_content($id);
get_footer($id);
}
private function get_headers($pageId){
$retrieveHead = $this->prepare("SELECT header FROM pages WHERE page_id=?");
$retrieveHead->bind_param('i',$pageId);
$retrieveHead->execute();
$retrieveHead->bind_result($header);
$retrieveHead->fetch();
$retrieveHead->close();
echo $header;
}
private function get_footer($pageId){
$retrieveFooter = $this->prepare("SELECT footer FROM pages WHERE page_id=?");
$retrieveFooter->bind_param('i',$pageId);
$retrieveFooter->execute();
$retrieveFooter->bind_result($footer);
$retrieveFooter->fetch();
$retrieveFooter->close();
echo $footer;
}
private function get_content($pageId){
$retreiveContent = $this->prepare("SELECT * FROM content WHERE page_id=? ORDER BY sequence");
$retreiveContent->bind_param('i',$pageId);
$retreiveContent->execute();
}
}
From what I can remember of mySQL, from here I would do a for loop but how would I go about doing this using this OOP approach and how would I then go about conducting the replacement of tags for each template?
My table structure can be found below. Hopefully this will make it more clear what I am looking for:
I'm guessing that in some way my query could be adapted to perform an inner join so that the code column from the templates table is also retreived but I've not really used joins with MySQLi before so I'm not sure if there is a specific way to write the syntax.
You can still loop using fetch. Filling the template should just be a case of str_replacing them:
private function get_content($pageId){
$theTemplate = grabTheTemplate();
$retreiveContent = $this->prepare("SELECT * FROM content WHERE page_id=? ORDER BY sequence");
$retreiveContent->bind_param('i',$pageId);
$retreiveContent->execute();
$retreiveContent->bind_result($foo, $bar,$baz);
while ($retreiveContent->fetch()) {
//$foo, $bar $baz will be populated for this row.
//Update the tags in the template.
$theTemplate = str_replace('tagToReplace','valueToReplaceWith',$theTemplate);
}
//$theTemplate is populated with content. Probably want to echo here
echo $theTemplate;
}
With Jim's help I have come up with the definitive solution:
private function get_content($pageId){
$retreiveContent = $this->prepare("SELECT template_id, section_title, i1, i2 FROM content WHERE page_id=? ORDER BY sequence");
$retreiveContent->bind_param('i',$pageId);
$retreiveContent->execute();
$retreiveContent->bind_result($template_id, $section_title, $i1, $i2);
while ($retreiveContent->fetch()) {
//Variables will be populated for this row.
//Update the tags in the template.
$theTemplate = grabTheTemplate($template_id);
$theTemplate = str_replace('[i1]',$i1,$theTemplate);
$theTemplate = str_replace('[i2]',$i2,$theTemplate);
//$theTemplate is populated with content. Probably want to echo here
echo $theTemplate;
}
}
As there can be multiple content items on a single page each of which could have a different template, I have moved the grabTheTemplate function call inside of the while loop so that the value from the template_id column can be used to retrieve the relevant template. I haven't tried this on my test server yet but in theory it should all work. I will try it this evening and edit this post if there are any bugs.
new to CodeIgniter and MVC/OOP as well. My current problem that I am trying to work through involves 2 tables.
Gallery Table
id
name
clientID
Client Table
id
Name
The gallery['clientID'] references the client['id'] so I can retrieve the name. Currently my gallery_model.php file looks like
class Gallery_model extends CI_Model
{
public function __construct()
{
$this->load->database();
}
//Get all in progress galleries from client
public function get_progress($id = FALSE , $clientRef = '205')
{
if($id == FALSE) {
$query = $this->db->get_where('gallery', array('clientRef' => $clientRef, 'finish' => '0' ));
return $query->result_array();
}
}
//Get all proofed galleries from client
public function get_proofed($id = FALSE , $clientRef = '205')
{
//get all galleries from client
if ($id == FALSE) {
$query = $this->db->get_where('gallery',array('clientRef' => $clientRef, 'finish' => '1'));
return $query->result_array();
}
}
//get the gallery selected
public function get_gallery($id , $clientRef = '205')
{
//This returns individual galleries
$query = $this->db->get_where('gallery', array('id' => $id));
return $query->row_array();
}
}
My controller looks like:
public function index()
{
//Proofed Albums
$data['gallery'] = $this->gallery_model->get_proofed();
//Albums that are in progress
$data['in_progress'] = $this->gallery_model->get_progress();
$this->load->view('templates/header',$data);
$this->load->view('gallery/index',$data);
$this->load->view('templates/footer');
}
Then the view's out put is
$gallery['name'] - $gallery['clientId']
What is the best practice for something like this. I know it's probably simple, but I want to start out doing this correctly. Should I use $this->db->join();
Thanks in advance for the help on this.
Following up on William's answer, you can do a join using CI's Active Record
$this->db->from('gallery')->join('client', 'gallery.id = client.id')->get()
Using $this->db->join() is indeed the best (and the only way done via Active Records without adding your own SQL) way to get information from several tables all in one query.
You're probably already aware of this, but just in case (and for the benefit of future people visiting this page), the CodeIgniter User Guide has a nice page detailing how to use Active Records.
The default of Inner Join should be fine for your purposes. If you have gallery entries without clients linked to them and you want them to be included in the results, then you may want to consider the other types of join, which you can read about here.
I hope the title was descriptive enough, i wasn't sure how to name it.
Let's say i have the following code:
Class Movie_model {
public method getMoviesByDate($date) {
// Connects to db
// Gets movie IDs from a specific date
// Loop through movie IDs
// On each ID, call getMovieById() and store the result in an array
// When all IDs has looped, return array with movies returned from getMovieById().
}
public function getMovieById($id) {
// Get movie by specified ID
// Also get movie genres from another method
// Oh, and it gets movie from another method as well.
}
}
I always want to get the same result when getting a movie (I always want the result from getMovieById().
I hope you get my point. I will have many other functions like getMoviesByDate(), i will also have getMoviesByGenre() for example, and i want that to return the same movie info as getMovieById() as well.
It it "ok" to do it this way? I know this puts more load on the server and increases load time, but is there any other, better way that i don't know of?
EDIT: I clarified the code in getMoviesByDate() a bit. Also, getMovieByDate() is just an example. As i said, i will be calling methods like getMoviesByGenre() also.
EDIT: I'm currently running 48 database queries on the frontpage of my project, and the frontpage is still far from finished, so that number would at least triple when i'm done. Almost all queries take around 0.0002, but as the database keeps growing that number will rise dramatically i'm guessing. I need to change something.
I don't think it's good to work like this in this particular case. The function getMoviesByDate would return an amount of "n" movies (or movie ids) from a single query. For each id in this query you would have a separate query to get the movie by the specified ID.
This would mean if the first function would return 200 movies, you would run the getMovieById() function (and the query inside it) 200 times. A better practice (IMO) would be to just get all the info you require in the getMoviesByDate() function and return it as a collection.
It doesn't seem very logical to have getMoviesByDate() and getMoviesById() methods on a Movie class.
An alternative would be to have some sort of MovieManager class that does all of the retrieving, and returns Movie objects.
class MovieManager {
public function getMoviesByDate($date) {
// get movies by date, build an array of Movie objects and return
}
public function getMoviesByGenre($genre) {
// get movies by genre, build an array of Movie objects and return
}
public function getMovieById($id) {
// get movie by id, return Movie object
}
}
Your Movie class would just have properties and methods specific to a single movie:
class Movie {
public id;
public name;
public releaseDate;
}
It's OK to have separate methods for getting by date, genre etc etc, but you must ensure that you are not calling for the same records multiple times - in that case you will want a single query that could join the various tables you need.
Edit - after you have clarified your question:
The idea of getting movie IDs by date, then running them all through getMovieById() is bad! The movie data should be pulled when getting by date, so you don't have to hit the database again.
You can modified your getMovieById function. You can pass date as a parameter, the function should return the movies by their id and filtered by date.
To keep track which records you've already loaded into RAM previously you can use a base class for your models which saves the id's of the records already loaded and a reference to object the model object in the RAM.
class ModelBase {
/* contains the id of the current record, null if new record */
protected $id;
// keep track of records already loaded
static $loaded_records = Array();
public function __construct(Array $attr_values) {
// assign $attr_values to this classes attributes
// save this instance in class variable to reuse this object
if($attr_values['id'] != null) {
self::$loaded_records[get_called_class()][$attr_values['id']] = $this;
}
}
public static function getConcurrentInstance(Array $attr_values) {
$called_class = get_called_class();
if(isset(self::$loaded_records[$called_class][$attr_values['id']])) {
// this record was already loaded into RAM
$record = self::$loaded_records[$called_class][$attr_values['id']];
// you may need to update certain fields of $record
// from the data in $attr_values, because the data in the RAM may
// be old data.
} else {
// create the model with the given values
$record = new $called_class($attr_values);
}
return $record;
}
// provides basic methods to update records in ram to database etc.
public function save() {
// create query to save this record to database ...
}
}
Your movie model could look something like this.
Class MovieModel extends ModelBase {
// additional attributes
protected $title;
protected $date;
// more attributes ...
public static function getMoviesByDate($date) {
// fetches records from database
// calls getConcurrentInstance() to return an instance of MovieModel() for every record
}
public static function getMovieById($id) {
// fetches record from database
// calls getConcurrentInstance() to return an instance of MovieModel()
}
}
Other things you could do do decrease the load on the DB:
Only connect once to the database per request. There are also possibilities to share a connection to a database between multiple requests.
Index thefields in your database which get searched often.
only fetch the records you need
Prevent to load the same record twice (if it didn't change)