I cannot get primary id array, I try to debug it happens when use joinLeft function
Here my script
//setIntegrityCheck to false to allow joins
$roomModel = new self();
$select = $roomModel->select(Zend_Db_Table::SELECT_WITH_FROM_PART)
->setIntegrityCheck(FALSE);
//performs join aliasing table room_type to t
$select->join(array('t' => 'room_types'), 't.room_type_id = rooms.room_type_id AND num_beds> '.$number_beds);
////performs join aliasing table room_status to s
$select->join(array('s' => 'room_statuses'), 's.room_status_id = rooms.room_status_id');
$select->joinLeft(array('chin' => 'checkin'), 'chin.checkin_date > '.$checkin.' AND chin.checkin_date <'.$checkout.'');
$select->joinLeft(array('chout' => 'checkout'), 'chout.checkout_date >'.$checkin.' AND chout.checkout_date <'.$checkout.'');
$result = $roomModel->fetchAll($select);
What causes it to happen?
one of the tables you are joining also may contain a column named like your primary key and if the row does not exist it will override it with null.
you should choose which columns you want from each table:
$select->join('table', 'condition', array('column1', 'column2', 'column3'));
$select->joinLeft('table', 'condition', array('column1', 'column2', 'column3'));
Related
My controller query is as below :
$built_arr = $this->User->query("SELECT u1.id,
CASE WHEN u1.role = 'CW' THEN u2.agency_name
WHEN u3.role = 'EU' THEN u2.agency_name ELSE u1.agency_name END AS agency
FROM users u1 LEFT JOIN users u2 ON (u1.parent = u2.id AND u2.role = 'A')
LEFT JOIN users u3 ON (u1.id = u3.parent AND u1.role = 'CW')
LEFT JOIN users u4 ON (u1.parent = u4.id AND u4.role = 'A')
WHERE u1.role = 'A' OR u1.role = 'CW'
GROUP BY u1.id");
And My code of array from this query is as below :
if (isset($built_arr) && !empty($built_arr)) {
foreach ($built_arr AS $key => $value) {
if (isset($value[0]['agency']) && !empty($value[0]['agency'])) {
$agency_arr[$value['u1']['id']] = $value[0]['agency'];
}
}
}
Now I have set this data to view like as below :
$this->set('agency_arr', $agency_arr);
Now this Array (agency_arr), I have used as data of columns of a table in view page.
Now I want to sort that column with this array data.
My view code as below :
<th><?php echo $this->Paginator->sort('?', __("Agency Name"), array('escape' => false)); ?></th>
Advice for the "?" sign.
What I have to write instead of "?", So I can sort with my array data.
My other column's data come from the paginate query so those are working fine.
I need this extra query for extra column, so need to sort by that column.
To the sort question:
Cake\View\Helper\PaginatorHelper::sort($key, $title = null, $options =[])
Parameters:
$key (string) – The name of the column that the recordset should be sorted.
$title (string) – Title for the link. If $title is null $key will be used for the title and will be generated by inflection.
$options (array) – Options for sorting link.
So i guess this is what you want: $paginator->sort('agency_name', 'Agency Name', array('escape' => false));
I would suggest to set up associations properly if you didnt already and use a find call with contains.
Since there are parents i guess its a HasAndBelongsToMany relation. (Children have multiple parents and parents multiple children)
CREATE TABLE `users` (
user_id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
role varchar(255),
);
CREATE TABLE `childrens_parents` (
childrens_parents_id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
parent_id int,
children_id int,
FOREIGN KEY (u1_id) REFERENCES users(user_id),
FOREIGN KEY (u2_id) REFERENCES users(user_id)
);
In your Model/UsersTable set up the association properly like described in
the cakephp book
(dont forget targetforeignkey+foreignkey)
Now you can do something like this:
$query = $this->Users->find()->where(['role'=>'A'])->orWhere(['role'=>'CW'])->contain([
'Children' => function ($q) {
return $q
->where(['Role =' => 'CW']);
}
])->contain([
'Parents' => function ($q) {
return $q
->where(['Role =' => 'A']);
}
])->group('user_id');
Now you can paginate over the resultset accessing all fields of the objects.
foreach($query as $row) {
debug($row);//see how nicely the resultarray is looking
echo($row->Parents[0]->user-id);// access related Entities
}
If its not HABTM but hasMany or some other type you can adapt it easily.
And I strongly recommend on holding in cake conventions !
Ressources (I recommend on reading the whole articles for proper cakephp work):
http://book.cakephp.org/3.0/en/orm/query-builder.html
http://book.cakephp.org/3.0/en/orm/associations.html
I'm new to ZF2 and I've got following problem :
In a db-table I got two id's that refered to another table. And if I
select them, I want to show the names of the players, rather than the
id's saved in the table.
player (id, name)
board (id, playerA, playerB)
playerA and playerB are integers and holding the id of a player, from the players table. I've got along with the skeleton-app, but the only clause I can pass to tableGateway->select() is the where-clause.
Does anyone have an idea? how can I prepare a statement like this in ZF2?
SELECT id, (SELECT name FROM player WHERE id = playerA) AS playerA, (SELECT name FROM player WHERE id = playerB) AS playerB FROM board
The tutorials and references I've found all ends up with a JOIN. But that do not fit here, right?
EDIT:
The following is it, what works fine with the skeleton app
protected $select;
public function fetchAll() {
$this->select = new Select();
$this->select->from('board')
->columns(array('id', 'kindOf', ...))
->join(['pA' => 'player'], 'pA.id = board.playerA', ['playerA' => 'name'])
->join(['pB' => 'player'], 'pB.id = board.playerB', ['playerB' => 'name']);
$resultSet = $this->tableGateway->selectWith($this->select);
return $resultSet;
}
Your problem is'nt a ZF2 problem but a SQL problem. You can write this for example :
SELECT id, pA.name AS playerA, pB.name AS playerB
FROM board
INNER JOIN player AS pA ON pA.id=board.playerA
INNER JOIN player AS pB ON pB.id=board.playerB
In ZF2 :
$select = new Select();
$select->from('board')
->columns('id')
->join(['pA' => 'player', 'pA.id = board.playerA', ['playerA' => 'name'])
->join(['pB' => 'player', 'pB.id = board.playerB', ['playerB' => 'name'])
I have the following query:
$result = Table1::model()->findAll(array(
'with' => array(
'table2' => array(
'joinType' => 'LEFT JOIN',
'on' => 'pk = fk AND fk=1'
)
),
'select' => array('name',
'COALESCE(table2.price, t.standardprice) AS price',
'COALESCE(table2.period, t.period) AS period')
)
);
My goal is to pick table2's fields if those are filled in, but if these are empty / no rows found the original table's fields should be displayed.
However, my output isn't as expected. The price field isn't displayed at all in my result's attributes, and the period field is either table2's value or empty.
EDIT: Perhaps my SQL is wrong somewhere. Using this SQL gives me the wanted results:
SELECT name, COALESCE(tb1.price, tb2.standardprice) as price, COALESCE(tb1.period, tb2.period) as period
FROM table1 as tb1
LEFT JOIN table2 as tb2
ON (tb1.pk= tb2.fk) AND fk=1;
Yet I don't see any difference with my current code.
EDIT2: Table structures:
Table1 (original table)
pk (int 11) - Primary key, auto increment
name (varchar 255)
standardprice (decimal 11,2)
period (varchar 255)
fkLanguage //not relevant
photo //not relevant
description //not relevant
link //not relevant
Table2
ID (int 11) - Primary key, auto increment
fk (int 11) - Foreign key, which links to pk of table1
period (varchar 255)
price (decimal 11,2)
fkType //not relevant
amount //not relevant
Clarification: The fk=1 is indeed a JOIN condition. If the fk isn't 1 then I don't want those rows to join, but take the values from table1 instead.
You need to add column price for parsing not existing column in schema.
Try to modify model Table1 ()
add public $price;
override method attributeNames to following:
public function attributeNames()
{
$colums = parent::attributeNames();
$colums[] = 'price';
return $colums;
}
I think you should do like this:
$result = Tablename::model()->findAll(array(
'with' => array(
'tabel2' => array(
'joinType' => 'LEFT JOIN',
'on' => 'pk = fk'
)
),
'select' => array('name',
'COALESCE(tabel2.price, t.standardprice) AS price',
'COALESCE(tabel2.period, t.period) AS period'),
'condition'=> ' fk = 1 '
));
because fk = 1 is not a part of the on statement; it is only a condition. I think that will make the difference for you.
I am trying to use ORM to access data stored, in three mysql tables 'users', 'items', and a pivot table for the many-many relationship: 'user_item'
I followed the guidance from Kohana 3.0.x ORM: Read additional columns in pivot tables
and tried
$user = ORM::factory('user',1);
$user->items->find_all();
$user_item = ORM::factory('user_item', array('user_id' => $user, 'item_id' => $user->items));
if ($user_item->loaded()) {
foreach ($user_item as $pivot) {
print_r($pivot);
}
}
But I get the SQL error:
"Unknown column 'user_item.id' in
'order clause' [ SELECT user_item.*
FROM user_item WHERE user_id = '1'
AND item_id = '' ORDER BY
user_item.id ASC LIMIT 1 ]"
Which is clearly erroneous because Kohana is trying to order the elements by a column which doesn't exist: user_item.id. This id doesnt exist because the primary keys of this pivot table are the foreign keys of the two other tables, 'users' and 'items'.
Trying to use:
$user_item = ORM::factory('user_item', array('user_id' => $user, 'item_id' => $user->items))
->order_by('item_id', 'ASC');
Makes no difference, as it seems the order_by() or any sql queries are ignored if the second argument of the factory is given.
Another obvious error with that query is that the item_id = '', when it should contain all the elements.
So my question is how can I get access to the data stored in the pivot table, and actually how can I get access to the all items held by a particular user as I even had problems with that?
Thanks
By default, all of Kohana's ORM models expect the table's primary key to be 'id.' You need to set $_primary_key in your model to something else.
$user_item = ORM::factory('user_item', array('user_id' => $user, 'item_id' => $user->items));
I think you need to provide a single item_id value for this to work, not an array of objects.
Also, to find all entries for a single user you should be able to do this:
$user_items = ORM::factory('user_item', array('user_id' => $user));
Does that answer your question?
I'm new to PHP/MySQL and super-new to CodeIgniter..
I have information in many MySQL tables. I want to retrieve it with JOIN where the tables primary keys are equal to $variable... How can I do it and get all the fields without the primary key field???
What I'm doing now is this (only two tables joined here):
function getAll($id) {
$this->db->select('*');
$this->db->from('movies');
$this->db->join('posters', 'movies.id= posters.id');
// WHERE id = $id ... goes here somehow...
$q = $this->db->get();
if ($q->num_rows() == 1) {
$row = $q->row();
$data = array(
'id' => $row->id,
'title' => $row->title,
'year' => $row->year,
'runtime' => $row->runtime,
'plotoutline' => $row->plotoutline,
'poster_url' => $row->poster_url
);
}
$q->free_result();
return $data;
id (PK), title, year, runtime and plotoutline are columns from the first table and poster_url is a field from the second table. The second table also contains an ID (PK) column that I don't want to Retrieve because I already have.
Jon is right. Here's an example:
$this->db->select('movies.id,
movies.title,
movies.year,
movies.runtime as totaltime,
posters.poster_url');
$this->db->from('movies');
$this->db->join('posters', 'movies.id= posters.id');
$this->db->where('movies.id', $id);
$q = $this->db->get();
This will return objects that have ->id, ->title, ->year, ->totaltime, and ->poster_url properties. You won't need the additional code to fetch the data from each row.
Don't forget, if the Active Record syntax gets a little unwieldy, you can use full SQL queries and get the same results:
$sql = "SELECT movies.id,
movies.title,
movies.year,
movies.runtime as totaltime,
posters.poster_url
FROM movies
INNER JOIN posters ON movies.id = posters.id
WHERE movies.id = ?"
return $this->db->query($sql, array($id))->result();
Both forms will ensure that your data is escaped properly.
CodeIgniter Active Record
Query Binding in CodeIgniter
An asterisk will return all the fields. To return a subset of these, i.e. all fields apart form the repeated id field, simply list the columns which you require rather than use '*'.
It is often a good idea to not use asterisk anyway. In the future of the app, someone may add a large field to the table which will be surplus to your requirements, and will slow your queries.
Simply put with method chaining:
$this->db->select('*')
->from('movies')
->join('posters', 'movies.id= posters.id')
->where('movies.id', $id)
->get();
$this->db->select('*');
$this->db->from('blogs');
$this->db->join('comments', 'comments.id = blogs.id');
$query = $this->db->get();