In CakePHP 3 ORM has changed and I can't find the proper way to select needed data from the database.
In CakePHP 2, I use contain('User.name','User.id'), but In CakePHP 3 this code doesn't work.
So how can I select only id and name from User?
The code:
$query = $data->find()->contain(['Users'])->execute()->fetchAll('assoc');
// I want only user.id and user.name.
$articles = $this->Model->find()
->select(['fields_you_want_from_this_Model'])
->contain(['Assoc_Model' => function($q) {
return $q
->select(['fields_you_want_from_the_associated_model']);
}]);
U must take a look about this page: http://book.cakephp.org/3.0/en/orm/query-builder.html#passing-conditions-to-contain
In certain case you must use autoFields method.
Be carefull with contain when u select few fields in the callable, u always have to select the foreign key also:
When you limit the fields that are fetched from an association, you must ensure that the foreign key columns are selected. Failing to select foreign key fields will cause associated data to not be present in the final result.
Related
I have a ProcessHistory and Person model I need a eloquent code for relation with multiple condition.
Conditions:
1. oindex = oindex
2. pat_id = pat_id
I want a eloquent code to get result of the following sql code
select * from tbl_process_history as s join tbl_persons as p on (s.oindex = p.oindex and s.pat_id = p.pat_id)
I need to get all the persons having same oindex and pat_id. I have tried with below eloquent code where I can apply condition inside of relation 'own'. Here I can apply only for as static value.
ProcessHistory::with(['own'=>function($query){
return $query->where('pat_id','');
}])->get();
I need a condition inside of relation where I can match pat_id of process history model with persons model.
I just found that I was actually searching for relationship with composite key but this feature is not provided in laravel. It can be solved by using https://github.com/topclaudy/compoships package.
ProcessHistory::with(['own'=>function($query) use ($param){
return $query->where('pat_id',$param);
}])->get();
I want to order by an aggregate function on an associated table's field, but when I debug the SQL query being executed, the associated table, PersonaHistory doesn't even get JOINed, and of course I don't get any results.
Is there a way to achieve this?
Can I force a table to be joined in the query?
$query = $this->Personas->find('all')
->contain(['PersonaHistory'])
->order(['MAX(PersonaHistory.updated)' => 'ASC'])
->group('PersonaHistory.persona_id');
DB: Personas has many PersonaHistory
It looks as if Personas is related to PersonaHistory via hasMany. Only hasOne and belongsTo associations produce a JOIN statement.
A workaround is to rewrite your query as:
$query = $this->PersonaHistory->find('all')
->contain(['Personas'])
->order(['MAX(PersonaHistory.updated)' => 'ASC'])
->group('PersonaHistory.persona_id');
your table name need to be plurialized and you can execute your order and group directly on your associated table field
<?php $query = $this->Personas->find('all')->contain([
'PersonaHistories' => function ($q) {
return $q->order(['Max(updated)' => 'ASC'])
->group('persona_id');
}]);
I think this is a common pattern, but I can't find the elegant CakePHP way of doing it. The idea is to remove the values from a list which have already been chosen. To use an example from the Cake book:
table Students (id int, name varchar)
table Courses (id int, name varchar)
table CoursesMemberships (id int, student_id int, course_id int, days_attended int, grade varchar)
All I want to do is create a query which returns the courses that a given student has not yet signed up for, most probably to populate a select dropdown.
If I weren't using Cake, I'd do something like
select * from Courses where id not in
(select course_id from CoursesMemberships where student_id = $student_id)
Or maybe an equivalent NOT EXISTS clause, or outer join trickery, but you get the idea.
I'm stumped how to do this elegantly in Cake. It seems to me that this would be a common need, but I've researched for awhile, as well as tried some query ideas, to no avail.
If you want to use a subquery, simply pass a query object as the condition value, like
$subquery = $Courses->CoursesMemberships
->find()
->select(['CoursesMemberships.course_id'])
->where(['CoursesMemberships.student_id' => $student_id]);
$query = $Courses
->find()
->where([
'Courses.id NOT IN' => $subquery
]);
As an alternative there's also Query::notMatching() (as of CakePHP 3.1), which can be used to select records whichs associated records do not match specific conditions:
$query = $Courses
->find()
->notMatching('CoursesMemberships', function (\Cake\ORM\Query $query) use ($student_id) {
return $query
->where(['CoursesMemberships.student_id' => $student_id]);
});
See also
Cookbook > Database Access & ORM > Query Builder > Subqueries
Cookbook > Database Access & ORM > Retrieving Data & Results Sets > Using notMatching
Cookbook > Database Access & ORM > Query Builder > Filtering by Associated Data
In CakePHP 3 you can create NOT IN query like this.
$query = $Courses->find()
->where(['id NOT IN' => $ids]);
And in CakePHP 3 you can create IN query like this.
$query = $Courses->find()
->where(['id IN' => $ids]);
You can read about it in CakePHP 3 Cookbook - Creating IN Clauses.
Found IMO the most elegant answer... use the notMatching() option:
$data = $this->Courses->find("list")
->notMatching("Students",
function($q) use ($student_id) {
return $q->where(["Students.id"=>$student_id]);
}
);
This assumes that Students HasMany Courses and Courses HasMany Students of course.
I think this is the most elegant answer since it doesn't depend on knowing any SQL, and represents the logic of what I'm trying to achieve using Cake's semantics only.
I am using cakephp2. How to delete a single record with a condition ?
I have a table named posts with fields id,title,post. primary key is id. I would like to delete the single record with id=5 ?
How it possible ?
That is I wands to convert the query,
$this->query('delete * from posts where id = 5'); To cakephp ?
How this function is write on cakephp modeln named Post ?
You can do it like this. $this->Model->delete(5);
or you can assign id to the model first and then delete it. Such as
$this->Model->id = 5;
$this->Model->delete();
If you want to execute a delete (or any other) query without a model then you should try
$db = ConnectionManager::getDataSource('default');
$db->rawQuery("DELETE FROM table WHERE id=5");
Use deleteAll().
$this->Model->deleteAll(array('Model.field_name'=>'field_value'));
OR delete by primary key:
1. $this->Model->delete(primary_key_value);
2. $this->Model->id = primary_key_value;
$this->Model->delete();
Hope it will help someone.
delete(int $id = null, boolean $cascade = true);
Deletes the record identified by $id. By default, also deletes records dependent on the record specified to be deleted.
Also you can apply function like in controller to delete one record
$this->Post->delete($this->request->data('Post.id'));
or if static id is known to you
$this->Post->delete(5);
please let me know if i can help you more
I have 3 tables in my SQLite database: User, Accounts, Passwords. The id of the Accounts and Passwords is a ForeignKey to User.id. The problem is that an instance of User doesn't have an id until it is saved (and django adds the Primary Field). This is how I am trying to do it, since the User.email should be unique then I should only get back one object but it isn't working. I'm sure there is a better way to do this.
tl;dr When I create a User, I also want an Accounts and Passwords table created for them, linked via a ForeignKey, id, which is also the PrimaryKey.
def adduser(request):
u = User(email=request.POST['email'], username=request.POST['username'], password=request.POST['password'])
a = Accounts()
u.save()
u = User.objects.get(email=request.POST['email'])
a.id = u.id
a.save()
This is much closer to what you want.
def adduser(request):
u = User(email=request.POST['email'], username=request.POST['username'], password=request.POST['password'])
u.save()
a = Accounts(
user=u
)
a.save()
Are you using django's User model?
if so you actually want this:
def adduser(request):
u = User(email=request.POST['email'], username=request.POST['username'])
u.set_password(request.POST['password'])
u.save()
a = Accounts(
user=u
)
a.save()
Also, rather than using request.POST variables everywhere, have you considered using django's forms and form utilities? They're quite nice.