Zend framework - zapytanie do MySQL

0

Mam problem ze zdefiniowaniem zapytania do MySQL w Zendie.
Zapytanie:

SELECT artykuly.id, artykuly.tytul, artykuly.tresc, artykuly.data_opb, artykuly.autor, votes.id_user, AVG(votes.ocena) AS ocena FROM artykuly LEFT JOIN votes ON artykuly.id=votes.id_artykul GROUP BY votes.id_artykul ORDER BY ocena {$this->filtr['sort-asc-desc']} {$limit}

Pomoże ktoś?
Sam głowię się nad nim cały dzień i nic wiele nie mogę wykombinować. Zajrzałem do manuala jednak nic nie znalazłem.
Wiem że trzeba użyć select() ->from(tutaj tabele ?) -> join(?) -> order(?) ->group(?);

1

Powinno to wyglądać mniej więcej tak:

$select = $this->select()->setIntegrityCheck(false); // setIntegrityCheck pozwala na dołączenie innej tabeli niż ta podana w modelu
// $select = $this->_db->select(); // tutaj nie trzeba stosować w/w metody ponieważ korzystamy z modelu ogólnego

$select->from(array('alias' => 'tableName'), array('columns', 'list'))
     ->joinLeft(array('alias' => 'joinTableName'), 'on clause', array('columns', 'list'))
     ->group(array('alias.columnName'))
     ->order(array('alias.columnName'))
     ->limit('count', 'offset');
0

@freemp3 - możesz sprawdzić?

$select->from(array('artykuly' => 'artykuly'), array('columns', array("id", "tytul", "tresc", "data_opb", "autor")))
     ->joinLeft(array('votes' => 'votes'), 'on clause', array('columns', 'array("id")'))
     ->group(array('votes.id_artykul'))
     ->order(array('ocena'))
     ->limit($limit);

Jeszcze sprawa odnośnie this->filtr['sort-asc-desc'] - to zwraca ASC lub DSC (czyli czy rosnąco/malejaco mają być posortowane) - gdzie to podpiąć?

0

zdaje się, że: order(array('ocena DESC'))

z tym że masz do wyboru ASC lub DESC, nie DSC

a jak sortujesz po jednej kolumnie to już w ogóle: ->order('ocena DESC')->

0
$select->from(array('artykuly' => 'artykuly'), array('columns', array("id", "tytul", "tresc", "data_opb", "autor")))
     ->joinLeft(array('votes' => 'votes'), 'on clause', array('columns', 'array("id")'))
     ->group(array('votes.id_artykul'))
     ->order('ocena '.$this->filtr['sort-asc-desc'])
     ->limit($limit);

Teraz jest wszystko OK?

1
$select->from(array('artykuly' => 'artykuly'), array('columns', array("id", "tytul", "tresc", "data_opb", "autor")))

Nie chodziło mi o to, że podajesz jako pierwszy element 'columns', a później liste kolumn, tylko że jest to lista kolumn jako tablica ;)

$select->from(array('artykuly' => 'artykuly'), array("id", "tytul", "tresc", "data_opb", "autor"))

Podobnie przy joinLeft.

  1. W joinLeft: 'on clause' w to miejsce powinieneś wstawić warunek, według którego tabele będą łączone.

  2. Przed dołączeniem zmiennej do order można jeszcze sprawdzić, czy aby na pewno znajduje się tam ASC lub DESC. Tak dla bezpieczeństwa :)

1

@freemp3
3. zależy skąd ta dana pochodzi, nie będzie błędem, gdy będzie to puste.

0

@dzek69
@freemp3

Niestety jest błąd w JOIN... - prawdopodobnie przez AVG(..) AS ocena

$limit = ($formulage['ilosc'] == "ALL") ? "" : "LIMIT {$formulage['ilosc']}";
                				
if($formulage['sort'] == "ocena") {
              $select->from(array('artykuly' => 'artykuly'), array(array("id", "tytul", "tresc", "data_opb", "autor"))
			->joinLeft(array('votes' => 'votes'), 'artykuly.id=votes.id_artykul', array("votes.id_user", "AVG(votes.ocena) AS ocena"))
			->group(array('votes.id_artykul'))
			->order('ocena '.$formulage['sort-asc-desc'])
			->limit($limit);
$this->view->articles = artykuly->fetchAll($select);
}

Dodatkowo mam jeszcze pytanie odnośnie Zenda.
Czy istnieje jakaś zmienna w Zendie, która widoczna jest w całym projekcie?
Chciałbym po UDANYM zalogowaniu usera do tej zmiennej przypisać jego nick -> coś na wzór $_SESSION['login'] = $nick;

0

Jeśli chcesz nadawać aliasy kolumnom to robisz to tak jak w przypadku tabel czyli:

array('alias'=>'kolumnaZAiliasem', 'kolumnaBezAliasu');
0

@freemp3

Nadal wywala błąd:
Parse error: syntax error, unexpected T_OBJECT_OPERATOR in (path)/application/controllers/PodstronyController.php on line 63

Linia 63:

->joinLeft(array('votes' => 'votes'), 'artykuly.id=votes.id_artykul', array("votes.id_user", array('ocena'=>'AVG(votes.ocena)', 'votes.ocena'))
0

Pokaż cały kod odpowiedzialny za tworzenie zapytania.
Po drugie

array("votes.id_user", array('ocena'=>'AVG(votes.ocena)', 'votes.ocena'))

Na liście kolumn nie dodaje się nowych tablic, wszystko ma znajdować się w jednopoziomowej tablicy:

array("votes.id_user", 'ocena'=>'AVG(votes.ocena)', 'votes.ocena')

Alias jest kluczem danego elementu, a nazwa kolumny wartością.

0

@freemp3
Cały akcja z Kontrolera. ...

0
  1. Wszystkie zapytania do bazy danych, obliczenia powinny znajdować się w modelu, czyli w Twoim przypadku zapytanie powinno być w klasie: Application_Model_DbBazaZF_Artykuly
  2. Powtórzę jeszcze raz: listę kolumn podajemy w tablicy jednopoziomowej, gdzie nazwy kolumn są jej wartościami, a jeśli chcesz podać alias dla jakiejś kolumny to podajesz nazwę aliasu jako nazwa klucza
$select->from('nazwa tabeli', array('kolumnaBezAliasu', 'alias' => 'kolumnaZAliasem', 'kolejnaKolumnaBezAliasu'))
  1. Popraw nawiasy przy from i leftJoin
  2. Przekazanie modelu do widoku?
$v = new Application_Model_Voter_MyVoter();
$this->view->voter = $v;
  1. Zapomniałeś znaku $ przed zmienną w dwóch miejscach.
0

@freemp3
Przeszło (nie wywala błędów) - niestety przy przesłaniu formularza zawsze wyświetla się wszystko (tak jaby nie uwzględniało tych innych zapytań)

public function artykulyAction()
    {
		$artykuly = new Application_Model_DbBazaZF_Artykuly();	
		$v = new Application_Model_Voter_MyVoter();
		$this->view->voter = $v;
		
        if ($this->_request->isPost()) {
			$formulage = $this->_request->getPost();				
			$this->view->filtr = $formulage;	
		
			if(isset($formulage['ilosc'])) {
                
                $limit = ($formulage['ilosc'] == "ALL") ? "" : "LIMIT {$formulage['ilosc']}";
                				
                if($formulage['sort'] == "ocena") {
                  $select = $artykuly->select()->from(array('artykuly' => 'artykuly'), array("id", "tytul", "tresc", "data_opb", "autor"))
							->joinLeft(array('votes' => 'votes'), 'artykuly.id=votes.id_artykul', array(array("votes.id_user", 'ocena'=>'AVG(votes.ocena)', 'votes.ocena')))
							->group(array('votes.id_artykul'))
							->order('ocena '.$formulage['sort-asc-desc'])
							->limit($limit);
							
					$this->view->articles = $artykuly->fetchAll($select);
					
				} else {
                    
					$select = $artykuly->select()->from(array('artykuly' => 'artykuly'))
							->order($formulage['sort'].' '.$formulage['sort-asc-desc'])
							->limit($limit);
							
					$this->view->articles = $artykuly->fetchAll($select);
                }
			}
		} else
		{	  
                $this->view->articles = $artykuly->fetchAll();
        }
	 	
	}
1
  1. Do metody limit podaje się liczbę, a nie część zapytania:
$limit = ($formulage['ilosc'] == "ALL") ? 0 : intval($formulage['ilosc']);
  1. Dalej nie jest poprawiona tablica kolumn w joinLeft

Poza tym niepotrzebnie robisz dwa podobne zapytania w dwóch miejscach. Możesz zrobić na początku bazowe, a później w zależności od warunków dodawać lub zmieniać jego elementy. Przede wszystkim pasowało by przenieść je do modelu i w parametrach metody przekazać warunki limitu i sortowania.

0

@freemp3 Wszystko śmiga elegancko.
Wielkie dzięki za pomoc!

BTW
Wiesz może jakiej zmiennej mogę użyć aby przypisać do niej nick zalogowanego usera (zmienna musi być widoczna w całym projekcie)
Szukam zamiennika dla $_SESSION['login'] = $nick;

1

Do autoryzacji i sprawdzania użytkowników powinno się używać Zend_Auth. Tutaj masz przykład jego wykorzystania: http://blog.wilgucki.pl/2010/03/praktyczne-wykorzystanie-zendauth.html
Na upartego jak już chcesz korzystać bezpośrednio z sesji to poczytaj o Zend_Session_Namespace.

1 użytkowników online, w tym zalogowanych: 0, gości: 1