Programozás

Programozással kapcsolatos ötletek, megoldások

MySQL count() függvény használata limit záradékkal

Bele is vágnék. Ki gondolta volna, hogy egyszer meg akarom számolni majd hány sort kérdeztem le adatbázisból, amikor használtam a limit záradékot, és én magam mondtam meg, hogy maximum hány sor lehet. Most mégis eljött ez a nap. Nézzük a következő lekérdezést:

select count(*) from tablaneve limit 40, 10

Logikusnak tűnne, hogy amennyiben van legalább 50 rekordom a tablaneve táblában, akkor visszaadja a 10-et a count(*) hatására, és ha nincs, akkor pedig annyit, amennyit le tudott kérdezni. De ez nincs így. Nem fog visszaadni egyetlen sort sem. Még csak nullát sem ad eredményül.

Mit lehet tehát tenni?

Létezik mysql-ben a found_rows() nevű furcsa függvény, amit meghívva megkapjuk az előző lekérdezésre illeszkedő sorok száma + a limitben megadott offset értéket. Tehát:

select * from tablaneve limit 40, 10;
select found_rows();

Megkapjuk, hogy 50, amennyiben volt legalább 50 sor. Ha csak 45 sor van az adatbázisban, akkor 45-öt eredményez. Az SQL_CALC_FOUND_ROWS opciót használva az első lekérdezésben azt lehet megmondani a mysql-nek, hogy az utána futtatandó found_rows() függvény hagyja figyelmen kívül a limit-et, és az összes sor számát adja vissza. Tehát:

select SQL_CALC_FOUND_ROWS * from tablaneve limit 40, 10;
select found_rows();

Kimenete lehet akár 300 is, ha a tablaneve táblában 300 rekord van.
Ezek ismeretében tehát a sorok számát meghatározhatjuk, ha az SQL_CALC_FOUND_ROWS használata nélkül lekérdezzük a rekordokat, majd a found_rows() visszatérési értékéből kivonjuk az offset értéket:

select * from tablaneve limit 40, 10;
select found_rows()-40;

Persze így lehet negatív szám is az eredmény. De ha ez probléma, akkor azon is segít egy if.

select * from teszt limit 40, 10;
select if(found_rows() < 40, 0, found_rows()-40);

A másik megoldás két egymásba ágyazott select, ahol a belső select eredménye tölti be a külső select-ben a tábla szerepét, és akkor már használható a count(*) is:

select count(*) from (select * from tablaneve limit 40, 10) as t

Aliast kötelező adni a belső select -nek.
Persze ha nem SQL-ben lett volna szükség erre a számolásra, akkor például PHP-ből meghívtam volna a lekérdezésre a mysql_num_rows() függvényt, és kész vagyok. De a leírtak arra adnak megoldást, amikor már sql-ben szükség van az értékre.

Megosztás/Mentés

Páros sorok megfordítása fájlban bash scripttel

Minek irkálok ilyen scripteket? Ez speciel egyetemi szorgalmi feladat volt, s ha már megírtam ne vesszen el szegény.

A Script:

if [ ! -f $1 ];
then
        echo "Első paraméter hiányzik, vagy nem létezik a fájl!"
        exit 1
fi
if [ $# -lt 2 ];
then
        echo "Második paraméter hiányzik"
        exit 1
fi

num=`wc -l $1 | cut -d" " -f1`
ret=();
i=0;
while  [ $num -gt 0 ];
do
        tmp=`tail -n ${num} $1 | head -n1`
        b=$((num % 2))
        if [ $b -eq 0 ];
        then
                ret[$i]=`echo $tmp | rev`
        else
                ret[$i]=`echo $tmp`
        fi
        let i++
        num=$((num-1))
done;
num=$i
while [ $i -gt 0 ];
do
        index=$((num-i))
        if [ $index -gt 0 ];
        then
                echo "${ret[$index]}" >> $2
        else
                echo "${ret[$index]}" > $2
        fi
        let i--
done;

Használata:
Mentsd el "rev.sh" néven, majd futtasd terminálban:

./rev.sh ./src.txt ./dst.txt

Ahol az src.txt a fájl, amiből olvas, és a dst.txt a fájl, amibe visszaírja az eredményt. Minden második sorát az src.txt -nek megfordítja és úgy írja be a dst.txt-be az src.txt tartalmát. A két fájl neve meg is egyezhet.

Megosztás/Mentés

Fájlok átnevezése kisbetűsre linuxon (rekurzív bash script)

Minden különleges idegen karaktert nem ismer, de a rename hívás után megadható a többi karakter mintájára új is.

#!/bin/bash

if [ $# -lt 1 ];
then
        echo "Add meg a mappa útvonalát!";
        exit 1
fi

function getftype()
{
        str=`ls -dl "$1"`
        echo ${str:0:1}
}

function tolowercase()
{
        cd "$1"
        for i in *
        do
                ftype=`getftype "$i"`
                if [ "$ftype" == "d" ];
                then
                        tolowercase "`pwd`/$i"
                fi
        done;
        rename 'y/A-ZÁÉÍÓÖŐÚÜŰ/a-záéíóöőúüű/' *
        cd ..
}

cd "$1"
tolowercase "`pwd`"

Használata:
Másold a fenti forráskódot egy tolcdc.sh ( to lowercase directory content ) nevű fájlba, majd futtasd terminálban a következőképpen.

./tolcdc.sh ./mappautvonala

Ahol a ./mappautvonala annak a mappának az útvonala, amiben rekurzívan szeretnéd átnevezni a a fájlokat, mappákat kisbetűsre.

Megosztás/Mentés

Javascript visszaszámláló - Napi sorsoló

Ebben a cikkben bemutatom, hogyan lehet olyan idő visszaszámláló szkriptet írni, ami minden nap egy konkrét időpontig számol vissza, de ez az időpont lehet a másnap reggeli időpont is akár. Ehhez figyelembe kell venni a szerveridőt is, másképp a kliens ( talán hibás ) órájára lenne bízva, hogy mikor van vége a visszaszámlálásnak. Persze a visszaszámlálásnak akkor van értelme, ha a végén valami történik is. Így szerveroldalon PHP-ból gondoskodni kell arról is, hogy például lefusson egy sorsoló program, ami aztán az eredményeket megjeleníti. Ezt vagy Crontab időzítővel, ha a tárhelyen rendelkezésre áll, vagy eltárolva például adatbázisban, hogy aznap lefutott-e már a sorsolás, és ha még nem, de az idő már lejárt, akkor fusson le. És írja ki az eredményt. Persze a következő sorsolásig a visszaszámlálás már elindul. Ennek megvalósítását mindenkinek magára bízom. Én csak a számlálást mutatom be.

Megosztás/Mentés

PHP grafika - R.E. PHP Graph v1.0

Törpi a sztár

Ez a program egy PHP grafikus osztálykönyvtár próbálna lenni. És úgy néz ki, hogy eddig sikerült is neki. némely részei 2 éve porosodnak a gépemen, és most gondoltam úgy, hogy eljött az ideje ezen változtatni.
Letöltés: R.E. PHP Graph v1.0
Dokumentáció letöltése
Dokumentáció online megtekintése
Példa képek


Tudnivalók:
A dokumentációban nagyjából minden le van írva. De azért nagy vonalakban miről is van szó. A Graph.class.php-t kell beilleszteni a programba elsőként. Majd létre kell hozni egy grafika objektumot, amire rá lehet pakolni egyéb objektumokat:

<?php
require_once 'rephpgraph/Graph.class.php';
$graph = new Graph(150,150);
$graph->type = 'png';
$graph->transparent = true;
?>

A szélességet és a magasságot kell csak megadni. Valamint megadható a kép típusa, és hogy legyen-e áttetsző a háttérszín. Ha szükség van objektumokra, akkor azt importálni kell a Graph osztály statikus importObject() metódusával. Ha paraméter nélkül hívjuk, akkor minden objektumot importál (Azaz osztályt). Ha stringet kap, akkor az osztály nevét kéri csak. Ha tömböt kap, akkor a tömbben kapja az osztályok neveit.
Az importIterator() ugyanezen elven működik. Csak iterátorokat importál.

Ezek után létre lehet hozni egy tetszőleges objektumot. És a $graph objektum add metódusával hozzá adható a képhez.

<?php
require_once 'rephpgraph/Graph.class.php';
$graph = new Graph(150,150);
$graph->type = 'png';
$graph->transparent = true;

$ora = new AnalogClock(74,mktime(7,10,30));
$ora->x = $graph->width-$ora->width/2;  //óra középpontjának koordinátái a képen
$ora->y = $graph->height-$ora->height/2;
$ora->background = $ora->createColor(0,0,130);
$ora->transparent = true;

$graph->add($ora); //óra felvétele  aképre

$graph->flush(); //kép megjelenítése

?>

A $graph objektum flush() metódusa küldi ki a képet a kimenetre. De lehetőség van lementeni is a képet a

<?php
$graph->save('fajlneve.png');
?>

metódushívással, vagy akár letöltésre kiküldeni a böngészőnek:

<?php
$graph->saveClient('fajlneve.png');
?>

Ennek kimenete:

Analóg óra
Természetesen az óra nem csak statikus időt tartalmazhat, hanem mindig az aktuális időt is.
Terveim közt szerepel még több objektum megírása, de egyelőre sok más elfoglaltság mellett halasztom a dolgot.

Megosztás/Mentés

Meghívós loginrendszer - R.E. login 1.8.1

R.E. Login 1.8.1

Egy csaknem 4 éves általam írt PHP loginrendszerről van szó, ami elég sok apró hibát tartalmazott. Most volt időm javítani ezeket a hibákat és 1.8.1 -es verziószámmal közzé is teszem.
Letöltés: R.E. Login v1.8.1
Képernyőképek

Megosztás/Mentés

PHP tortadiagram kezelő v1.1

Tortadiagram

Ez a php program Különböző adatok egymáshoz viszonyított arányát ábrázolja tortadiagramon.
Használatához mysql adatbázisra van szükség. Az adatbázis kapcsolódáshoz szükséges adatokat a config.php-ben lehet beállítani. Az 1.0 verzióhoz képest nem változott semmi, csak hibajavítások történtek. 4 éve még nem figyeltem az apróságokra annyira. Illetve beépítettem egy kijelentkezést is.
Letöltés: Tortadiagram kezelő v1.1


Telepítése
Ha a config.php-t beállítottad, másold fel a fájlokat a szerverre, és nyisd meg az index.php-t. Ekkor a telepítés megtörténik, és az sql.sql fájlt törli a program.
Ha az adatok helyesek a config.php-ben, de mégsem sikerül a telepítés, lehet, hogy már létezik a diagram tábla az adatbázisban. Ekkor ezt törölni kell és újra próbálkozni.

Adminisztráció
Mindent az admin.php oldalon tudsz beállítani. Nyisd meg ezt a szerveren böngészőből, és kezdd el felvenni az adatokat. Beállíthatod milyen színnel jelenjen meg a diagramon bármelyik adat. Törölhetsz és módosíthatsz. Jelszó szükséges. Alapértelmezetten: "password". De ezt is beállíthatod a config.php-ben.

Használata
Ahol a diagramot a mellette található színmagyarázatokkal megjelenítenéd, használd a következő php kódot:

<?php include('tortadiagram/inc.php'); ?>

Ahol feltételeztem, hogy diagram fájljait a tortadiagram mappában lehet megtalálni.
Ha csak a tortadiagramra van szükség, akkor a következő html kód használható:
<img src="tortadiagram/diagram.php" alt="diagram" />

Képernyőképek

Megosztás/Mentés

JavaScript, mind kijelöl funkció

Tegyük fel, Sok sok pici checkbox van a weboldalon. Például kijelölhetők a törlendő üzenetek. De fárasztó egyenként kattintgatni. JavaScripttel egyszerre kijelölhető akár mind is.
A következőkben erre mutatok megoldást, illetve egy kipróbálható demót is.


Induljunk ki a következő html forrásból:

<div id="checkall1">
        Első sor:<br />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />

</div>
<div id="checkall2">
        Második sor:<br />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
        <input type="checkbox" />
</div>

Két csoport checkbox van. Mindkettő egy div-ben, aminek egyedi id-je van. Így lehet csak az egyik, vagy másik csoportra hivatkozni, ha egyszerre több "Mind kijelöl" funkcióra is szükség van egy oldalon. Lehetne persze class-okat adni az inputoknak, vagy a nevet megadni tömbként stb stb... De ez a legtisztább megoldás szerintem.

Kellene most két újabb checkbox, vagy akár gomb, amire kattintva változik a többi jelölőnégyzet állapota. Ebben a példában ezt a funkciót is egy checkbox tölti be. Mérete is kisebb, és könnyebb ellenőrizni, hogy mire kell váltani az állapotokat.

<input type="checkbox" onclick="checkAll(this, 'checkall1');" /> Első sor kijelölése<br />
<input type="checkbox" onclick="checkAll(this,'checkall2');" /> Második sor kijelölése

Az onclick eseményben található checkAll függvény felel a jelölések változtatásáért. Első paramétere mindig a this. Így a függvényben kattintás után elérhető az input mező objektuma, és lekérdezhető annak a checked tulajdonsága, ami megadja, ki van-e jelölve az adott checkbox. Második paraméter pedig annak a tároló elemnek az azonosítója, amiben a jelölendő checkboxok vannak.

Már csak függvényt kell megírni.
Legyen ez például a checkall.js nevű fájl. Annak tartalma pedig a következő:

function checkAll(chbx,id)
{
        var checked = chbx.checked;
        var container = document.getElementById(id);
        if (!container) return;

        var inputs = container.getElementsByTagName('input');
        for (var i in inputs)
        {
                if (inputs[i].type != 'checkbox') continue;
                inputs[i].checked = checked;
        }
}

Ebben, ha hibás azonosítót kapott a checkAll függvény, nem történik semmi. De ha megtalálta a tároló elemet az azonosítóval, akkor lekérdezi az összes input elemet belőle egy tömbbe. Ez után már csak egy ciklus kell, amiben az összes checkbox típusú input mező checked tulajdonságát beállítjuk ugyanarra, amilyen a kapcsolgató checkboxunké.

Kitérő:
A for-in ciklus hasonló a PHP-ben ismert foreach-hez. Az in után álló tömb összes indexét egymás után betölti az in előtt álló változóba. Így nem kell lekérdezni hány eleme van a tömbnek. És azt sem kell tudni, milyen indexek vannak benne.

Megosztás/Mentés

Webes fájlkezelő php-ben

Fájlkezelő

Ezt a fájlkezelőt még a phpstudio-ra készítettem 2006 szeptemberében.
A kezelése és a megjelenése nem a legpraktikusabb / legmodernebb, de azért még így is hasznát lehet venni :)
Letöltés: Fájlkezelő


Amit tud
A fájlkezelõ képes mappákat, fájlokat másolni, áthelyezni, átnevezni, létrehozni, törölni.
Fájlokat meg is nyithatsz, és módosíthatod. Hasznos lehet apróbb hibák esetében, ha nem akarsz ftp-t használni.
Lehetőség van fájlok feltöltésére. Maximum 2MB lehet a fájlméret.

Beállítások:
A fajlkezelo.php nevű fájl elején megtalálod a $konyvtar változót.
Állitsd be azt a mappát, ahova szeretnéd tenni a feltöltött fájlokat.
pl : $konyvtar = "temp";
A belépéshez még szükség van egy jelszóra. Ezt is a fajlkezelo.php elején teheted meg.
Töltsd fel a fajlkezelo.php fájt a szervered gyökérkönyvtárába, és máris tallózhatsz a fájlok között.

Használata
Válaszd ki a mappát, ahonnan szeretnéd listázni a fájlokat. Ezt megtalálod a "honnan" link mellett.
Majd válaszd ki, hogy hova szeretnél másolni, áthelyezni, stb... Ezt pedig a hova link mellett találod.
Ha egy szintet feljebb szeretnél ugrani a mappákban, akkor válaszd az >>1 szint fel<< opciót.

Miután a fájlok listája megjelenik, válaszd ki a fájlt, amivel dolgozni szeretnél. És jelöld ki azt másolást, vagy az áthelyezést attól függöen, mit szeretnél a fájllal. Lehetõség van a fájlok átnevezésére. Ezt akár a másolás, akár az áthelyezés opcioval is megteheted. Ha csak másolni szeretnél ugyanabba a mappába, ahol a forrásfájl található, csak jelöld ki a másolást, és nevezd át a fájlt. A cél mappa (hova) egyezzen.

Ha már egy meglévő fájlt, pl egy php szkriptedet szeretnéd feltölteni, azt is megteheted.

Ha egy meglévő fájlt szeretnél szerkeszteni, válaszd ki a fájlok listájában a fájlt, és kattints a szerkeszt linkre.
Itt módosíthatod a fájlokat. A megnyitás csak szöveges fájlok esetében működik. Így például nem tudsz megnyitni képfájlokat szerkesztésre.

Fájlok méretét is megnézheted. Amikor kiválasztod a fájlt, automatikusan megjelenik az oldal tetején a mérete a nevével együtt.

Megosztás/Mentés