When I call images from the database random, it loads them x times, but I want to show them only once.
$random = array_rand(Database::query('SELECT * FROM ADVERTISEMENTS' ));
$adv_sql = "SELECT * FROM `ADVERTISEMENTS` WHERE `id` = $random ";
$advResult = Database::single($adv_sql, $random['id']);
$advExplode = explode('/', $advResult['upload']);
$advLocation = 'url/location' . end($advExplode);
I cannot understand your abstraction.
Your second query has condition id = $random, but you bind params in your single() method: $adv_sql, $random['id'].
We don't know your methods work, you should have shown us their implementation.
Anyway, isn't one query better for this?
SELECT * FROM `ADVERTISEMENTS` ORDER BY RAND() LIMIT 1
Or without LIMIT if you want to recieve all
If you don't want to show an already loaded image in the second request, you'd need to log which images where shown so far, into a database, cookies or sessions, depending on the needs.
Or, bind the shown images to an instance.
This is my test so far:
class Images {
private $_imagesShown = array("''");
private function getShownImages() {
return implode(',', $this->_imagesShown);
}
private function setShownImage($row) {
$this->_imagesShown[] = $row['id'];
}
public function getImages() {
$query = "SELECT id, image FROM images WHERE id NOT IN ({$this->getShownImages()})";
$result = mysqli_query($query);
$row = mysqli_fetch_assoc($result);
$this->setShownImage($row);
return $row;
}
}
$img = new Images();
var_dump($img->getImages());
var_dump($img->getImages());
var_dump($img->getImages());
var_dump($img->getImages());
var_dump($img->getImages());
var_dump($img->getImages());
var_dump($img->getImages());
var_dump($img->getImages());
Outputs:
array (size=2)
'id' => string '1' (length=1)
'img' => string '0.jpg' (length=1)
array (size=2)
'id' => string '2' (length=1)
'img' => string '1.jpg' (length=1)
array (size=2)
'id' => string '3' (length=1)
'img' => string '2.jpg' (length=1)
array (size=2)
'id' => string '4' (length=1)
'img' => string '3.jpg' (length=1)
array (size=2)
'id' => string '5' (length=1)
'img' => string '4.jpg' (length=1)
array (size=2)
'id' => string '6' (length=1)
'img' => string '12.jpg' (length=1)
array (size=2)
'id' => string '7' (length=1)
'img' => string '55.jpg' (length=1)
so each call of getImages() returns a non shown image
Related
I want this code to accept more than one WHERE parameter at the bottom, but when the added text comes into play, it returns nothing. It returns what it should without the filter.
What I'm trying to do is filter the results I get from the inner query from user inputted data that gets posted into the PHP code.
Any advice would be helpful at this point.
$OgrenciNo= " AND OgrenciNo LIKE %1005%";
$sth = $conn->prepare('SELECT t.* FROM (SELECT ogrenciler.OgrenciNo, ogrenciler.adsoyad as adsoyad1,
dersler.Ders, dersler.DersKodu, tarih.Tarih, ogretmenler.isim,
login.adsoyad, onayturu.Onay, mazeretturu.tur,
mazeretaciklama.Aciklama, mazeretaciklama.LogTarihi
FROM ogrenciler, tarih, aratablo, ogretmenler,
mazeretaciklama, login, dersler, mazeretturu, onayturu
WHERE aratablo.AciklamaID = mazeretaciklama.AciklamaID
AND aratablo.TarihID = tarih.TarihID
AND aratablo.DersID = dersler.DersID
AND aratablo.OnaylayanID = login.OnaylayanID
AND aratablo.OnayID = onayturu.OnayID
AND aratablo.Mazturu = mazeretturu.Mazturu
AND dersler.OgrGorID = ogretmenler.OgrGorID
AND mazeretaciklama.OgrenciNo = ogrenciler.OgrenciNo) t
WHERE LogTarihi > "1900-01-01"
'.$OgrenciNo
);
$sth->execute();
Normal results are as follows:
array (size=2)
0 =>
array (size=11)
'OgrenciNo' => string '1005.02021' (length=10)
'adsoyad1' => string 'Örnek Öğrenci' (length=13)
'Ders' => string 'Ders Adı' (length=8)
'DersKodu' => string 'KOD000' (length=6)
'Tarih' => string '2016-02-01' (length=10)
'isim' => string 'Öğretim Elemanı İsmi' (length=20)
'adsoyad' => string 'ROOT' (length=4)
'Onay' => string 'Onaylandı' (length=9)
'tur' => string 'Sınav' (length=5)
'Aciklama' => string 'hastalık hastası' (length=16)
'LogTarihi' => string '2016-02-09 09:14:52' (length=19)
1 =>
array (size=11)
'OgrenciNo' => string '1035.02021' (length=10)
'adsoyad1' => string 'ahmet mehmet' (length=12)
'Ders' => string 'E-Ticaret Sistem Tasarımı' (length=25)
'DersKodu' => string 'BIL446' (length=6)
'Tarih' => string '2016-02-07' (length=10)
'isim' => string 'Yrd. Doç. Dr. Mustafa Cem Kasapbaşı' (length=35)
'adsoyad' => string 'Araş. Gör. Erdem Yavuz' (length=22)
'Onay' => string 'Onaylanmadı' (length=11)
'tur' => string 'Ders' (length=4)
'Aciklama' => string 'cenaze vardı' (length=12)
'LogTarihi' => string '2016-02-11 13:33:53' (length=19)
I'm trying to filter out the second result but the LIKE argument doesn't seem to work.
By popular demand here's the whole query after I print it out in the page (P.S. the only thing different from the top one is that it contains "AND OgrenciNo LIKE %1005%" at the end):
SELECT t.* FROM (SELECT ogrenciler.OgrenciNo, ogrenciler.adsoyad as adsoyad1, dersler.Ders, dersler.DersKodu, tarih.Tarih, ogretmenler.isim, login.adsoyad, onayturu.Onay, mazeretturu.tur, mazeretaciklama.Aciklama, mazeretaciklama.LogTarihi FROM ogrenciler, tarih, aratablo, ogretmenler, mazeretaciklama, login, dersler, mazeretturu, onayturu WHERE aratablo.AciklamaID = mazeretaciklama.AciklamaID AND aratablo.TarihID = tarih.TarihID AND aratablo.DersID = dersler.DersID AND aratablo.OnaylayanID = login.OnaylayanID AND aratablo.OnayID = onayturu.OnayID AND aratablo.Mazturu = mazeretturu.Mazturu AND dersler.OgrGorID = ogretmenler.OgrGorID AND mazeretaciklama.OgrenciNo = ogrenciler.OgrenciNo) t WHERE LogTarihi > "1900-01-01" AND OgrenciNo LIKE %1005%
Your like condition should be like this. Just add ' in it. :
$OgrenciNo= " AND OgrenciNo LIKE '%1005%'";
In Codeigniter I am tryign to join two tables with a one-to-many relation. I want to get one result from my table housetype and all of its values/members from other table housetype_member:
$this->db->select('*');
$this->db->join('housetype_member', 'housetype_member.housetype_id = housetype.PkId', 'left');
$result = $this->db->get_where('housetype', array('PkId' => $id));
return $result->result();
So far I get such result:
array (size=2)
0 =>
object(stdClass)[28]
public 'PkID' => string '4' (length=1)
public 'Name' => string 'Classic' (length=7)
public 'image' => string '1449063250.jpg' (length=14)
1 =>
object(stdClass)[30]
public 'PkID' => string '4' (length=1)
public 'Name' => string 'Classic' (length=7)
public 'image' => string '1449063288.gif' (length=14)
First two object values (PkID, Name) are from the first table and the last one (image) is from the second left table. Everything is good but I get an array with two elements, when I only need one housetype object.
Is there a way to write above code so that my returned object would look like this:
object(stdClass)[28]
public 'PkID' => string '4' (length=1)
public 'Name' => string 'Classic' (length=7)
public 'image' =>
array (size=2)
0 => string '1449063250.jpg' (length=14)
1 => string '1449063288.gif' (length=14)
I need one result from the first table and to it I want to join all of its members from the second table.
Can it be done with Codeigniters active record, can it be done at all?
Add group_by() clause to your query.
$this->db->group_by('housetype.PkId');
i'm working on a small text based web game for a few friends to play (for nostalgia) but i'm having trouble with the very core of the game, the attacking/defending.
Each player has x amount of each troop type (more can be purchased and will be lost on atk/def)
so far I have a table with troop types and stats and a table with troop qty linked with user id and troop id.
I'm using the user id to get the troop id and qty using;
// Get attacker troop quantities.
$i = 0;
$attacker_deets = $conn->prepare("SELECT * FROM troop_qty WHERE user_id= :attacker_id");
$attacker_deets->bindParam(':attacker_id', $attacker_id);
$attacker_deets->execute();
$attacker_deets_results = $attacker_deets->fetchAll(PDO::FETCH_ASSOC);
foreach($attacker_deets_results as $atk_key=>$atk_result) {
echo "<pre>"; var_dump($atk_result); echo "</pre>";
}
which outputs;
array (size=4)
'troop_qty_id' => string '1' (length=1)
'user_id' => string '2' (length=1)
'troop_id' => string '1' (length=1)
'qty' => string '100' (length=3)
array (size=4)
'troop_qty_id' => string '2' (length=1)
'user_id' => string '2' (length=1)
'troop_id' => string '2' (length=1)
'qty' => string '100' (length=3)
I'm then using the troop id to get the troop details;
// get attacker troop details.
$attacker_troop_deets = $conn->prepare("SELECT * FROM troops WHERE troop_id= :atk_troop_id");
$attacker_troop_deets->bindParam(':atk_troop_id', $attacker_deets_results[$i]['troop_id']);
$attacker_troop_deets->execute();
$returned_results = $attacker_troop_deets->fetchAll(PDO::FETCH_ASSOC);
foreach($returned_results as $key=>$result) {
echo "<pre>"; var_dump($result); echo "</pre>";
}
++$i;
which in total gives me;
array (size=4)
'troop_qty_id' => string '1' (length=1)
'user_id' => string '2' (length=1)
'troop_id' => string '1' (length=1)
'qty' => string '100' (length=3)
array (size=4)
'troop_id' => string '1' (length=1)
'troop_name' => string 'Fist Puncher' (length=12)
'troop_atk' => string '1' (length=1)
'troop_def' => string '1' (length=1)
array (size=4)
'troop_qty_id' => string '2' (length=1)
'user_id' => string '2' (length=1)
'troop_id' => string '2' (length=1)
'qty' => string '100' (length=3)
array (size=4)
'troop_id' => string '2' (length=1)
'troop_name' => string 'Stick Waver' (length=11)
'troop_atk' => string '2' (length=1)
'troop_def' => string '1' (length=1)
Now where i'm stuck is I need to be able to compare the troop_atk of First Puncher with the defence of Stick Waver which is gotten from a different set of duplicate query's getting the defenders details, i also need to be able to multiply and divide the atk and def variables.
so how would i go about achieving this? i would assume i would need to give each field in the array their own variable, but how? i have tried using ${"troop_name" . $i} = $attacker_deets_results[$i]['troop_name']; but it only ever outputs the last entered name.
any help would be amazing. thanks.
Edit: To clear things up a little, my goal is to get the troop qty and multipy it by both atk and def then use these numbers to do some other math with the same fields from the defending player which I'll use to decrease the qty field.
Maybe you could modify your code a little and do the following.
Fetch the data about the user's troops in one query:
$results = $conn->query("SELECT troop_qty.user_id as uid, troop.troop_id, troop.troop_name, troop_qty.qty, troop.troop_atk, troop.troop_def FROM troop_qty join troop on troop.troop_id=troop_qty.troop_qty_id WHERE troop_qty.user_id=:attacker_id
Create a new array which contains information about all user's troops:
$userData = array(
'id' => $attacker_id,
'troops' => array());
while (($res = $results->fetch_assoc()) != null) {
$troopData = array(
'name' => $res['troop_name'],
'qty' => $res['qty'],
'atk' => $res['troop_atk'],
'def' => $res['troop_def']);
$userData['troops'][$res['troop_id']] = $troopData;
}
As result you would have something like this (vardump($userData)):
array (size=2)
'id' => int 2
'troops' =>
array (size=2)
1 =>
array (size=4)
'name' => string 'Fist Puncher' (length=12)
'qty' => string '100' (length=3)
'atk' => string '1' (length=1)
'def' => string '1' (length=1)
2 =>
array (size=4)
'name' => string 'Stick Waver' (length=11)
'qty' => string '100' (length=3)
'atk' => string '2' (length=1)
'def' => string '1' (length=1)
I don't know how exactly you want to manipulate the data later on in the game but I think this would ease the work.
Btw. I've thrown away fetchAll() function because I personaly think it is not a good practice to fetch all data into memory and then modify it or do whatever with it. It's a waste of the memory and when you would deal with a big amount of data, at some point that could cause you some troubles.
I want to get Doctrine to return a hydrated array with the values being the id for the key, then all values inside an array of results (i.e. if there are multiple items with same ID, then return ID with multiple results in array).
This is the current function I do:
public static function getMedia($em, $entity, $id = NULL)
{
$dql = 'SELECT m.id, m.url, m.nb, m.lang
FROM iMT\Entity\Media m INDEX BY m.id JOIN iMT\Entity\\' . $entity . ' r WITH m.id = r.id';
if($id) {
$dql .= " WHERE r.id = ?1";
}
$q = $em->createQuery($dql);
if($id) {
$q->setParameter(1, $id);
}
return $q->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
}
Which returns:
array (size=44)
479600 =>
array (size=4)
'id' => int 479600
'url' => string 'pois/479600/Nonna.JPG' (length=48)
'nb' => null
'lang' => string 'fr' (length=2)
479615 =>
array (size=4)
'id' => int 479615
'url' => string 'pois/479615/Tramways.jpg' (length=51)
'nb' => null
'lang' => string 'fr' (length=2)
479580 =>
array (size=4)
'id' => int 479580
'url' => string 'pois/479580/ATLAS.jpg' (length=48)
'nb' => null
'lang' => string 'fr' (length=2)
479581 =>
array (size=4)
'id' => int 479581
'url' => string 'pois/479581/P'tit_sushi.jpg' (length=54)
'nb' => null
'lang' => string 'fr' (length=2)
However, I need the output to be:
array (size=44)
479600 =>
array (size=2)
array (size=4)
'id' => int 479600
'url' => string 'pois/479600/Nonna.JPG' (length=48)
'nb' => null
'lang' => string 'fr' (length=2)
array (size=4)
'id' => int 479600
'url' => string 'pois/479600/OtherPic.JPG' (length=48)
'nb' => null
'lang' => string 'fr' (length=2)
Would I need to create my own AbstractQuery::HYDRATE_ARRAY or is there something available that does what I need?
I'm using the result by checking if it contains a key that matches the ID of the current item (e.g. if(isset($data[$item])) // where $item = 479600 then output images), maybe there's a better way to check for the results?
EDIT
I've updated my function to return:
$result = $q->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
$data = array();
$count = count($result);
for($i = 0; $i < $count; $i++) {
if(!isset($data[$result[$i]['id']])) {
$data[$result[$i]['id']] = array(
$result[$i]
);
} else {
$data[$result[$i]['id']][] = $result[$i];
}
}
return $data;
Which returns something more to what I want:
array (size=44)
479600 =>
array (size=1)
0 =>
array (size=4)
'id' => int 479600
'url' => string 'pois/479600/Nonna.JPG' (length=48)
'nb' => null
'lang' => string 'fr' (length=2)
479577 =>
array (size=2)
0 =>
array (size=4)
'id' => int 479577
'url' => string 'pois/479577/AOMC.JPG' (length=47)
'nb' => null
'lang' => string 'fr' (length=2)
1 =>
array (size=4)
'id' => int 479577
'url' => string 'pois/479577/Buffet AOMC.jpg' (length=54)
'nb' => null
'lang' => string 'fr' (length=2)
Can this be improved? Is there any Doctrine functions that can help, or should I leave my for() loop?
The problem with using INDEX BY together with a JOIN is that the result that doctrine gives you might not contain all data that's fetched from the database.
In your case the database might return multiple rows containing the same value for m.id (because of the JOIN). But each subsequent row containing the same value for m.id will overwrite the previous one (because of the INDEX BY m.id).
Doctrine does not come with a hydrator that can solve this problem out of the box. You shall indeed need to implement your own. Read more about creating custom hydration modes.
Alternative
Another solution would be to not use INDEX BY in this case.
You could write a repository method that translates the result given by Doctrine to the array you want to have. Other parts of your application can then call that repository method.
This is probably easier than creating a custom hydration mode.
Update
The translation can look like this:
$data = array();
foreach ($q->getArrayResult() as $row) {
if (!isset($data[$row['id']])) {
$data[$row['id']] = array();
}
$data[$row['id']][] = $row;
}
return $data;
I have a var dump of my sql query which return the following
I wanna to count in the array below that how many rows of myID = 5 are there. How would I do that. I am using php. Thanks in advance
array
0 =>
object(stdClass)[17]
public 'myID' => string '5' (length=1)
public 'data' => string '123' (length=3)
1 =>
object(stdClass)[18]
public 'myID' => string '5' (length=1)
public 'data' => string '123' (length=3)
2 =>
object(stdClass)[19]
public 'relativeTypeID' => string '2' (length=1)
public 'data' => string '256' (length=3)
3 =>
object(stdClass)[20]
public 'myID' => string '4' (length=1)
public 'data' => string '786' (length=3)
object(stdClass)[21]
public 'myID' => string '4' (length=1)
public 'data' => string '786' (length=3)
Do you always have the same value of data for the same myID? In other words, is data functionally dependant on myID?
If so, you can get the database to do this for you:
SELECT myID, data, COUNT(*) AS cnt
FROM (your query here)
GROUP BY myID, data
This would give you results like the following:
myID data cnt
'5' '123' 3
'2' '256' 1
'4' '786' 2
Or, you can use a foreach statement, like:
$count = 0;
foreach($arr as $item)
{
// Given that your item is an stdClass Object you access its property with "->"
// if an array $item["myID"] instead
if ( $item->myID == '4' )
{
$count ++;
}
}