I am trying to do login system in cakephp 3.
Here is the query:
$user_details = $this->User->find('first', ['conditions'=>['email_id'=$email, 'password'=>$password]]);
if(!empty($user_details)){
$this->request->session()->write('user_email'=>$user_details['email_id']);
$this->request->session->write('user_id'=>$user_details['id');
}
Can you tell the differences from cakephp 2 to cakephp 3 about writing queries?
try this query its work fine for you...
$user_details = $this->User->find('first', ['conditions'=>['User.email_id'=$email, 'User.password'=>$password]]);
otherwise you get help from http://book.cakephp.org/3.0/en/controllers/components/authentication.html
For authenticating users you should use the Authentication component. This serves as the best implementation within CakePHP as it automatically binds all the data to the server and request.
public function initialize()
{
parent::initialize();
$this->loadComponent('Auth', [
'loginAction' => [
'controller' => 'Users',
'action' => 'login',
'plugin' => 'Users'
],
'authError' => 'Did you really think you are allowed to see that?',
'authenticate' => [
'Form' => [
'fields' => ['username' => 'email']
]
],
'storage' => 'Session'
]);
}
Please refer to the documentation: http://book.cakephp.org/3.0/en/controllers/components/authentication.html
To answer your original question
Cake 2 uses an automagical function with an array structure for building queries which is quite devious. The query is executed directly on call.
array(
'conditions' => array('Model.field' => $thisValue), //array of conditions
'recursive' => 1, //int
//array of field names
'fields' => array('Model.field1', 'DISTINCT Model.field2'),
//string or array defining order
'order' => array('Model.created', 'Model.field3 DESC'),
'group' => array('Model.field'), //fields to GROUP BY
'limit' => n, //int
'page' => n, //int
'offset' => n, //int
'callbacks' => true //other possible values are false, 'before', 'after'
)
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html
Within Cake 3 the query is built using a query builder object. This modifies the SQL on every subsequent call. It is only executed after you call it to.
$query = $articles->find('all')
->where(['Articles.created >' => new DateTime('-10 days')])
->contain(['Comments', 'Authors'])
->limit(10);
Here the an object is manipulated with a referenced SQL on every call (where, contain, limit).
The query is executed after you apply execute(), first(), toArray() etc, where toArray() returns the data set as an array and others as an object.
Further reading: http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html
Related
I'm using 2 tables with 1 to many relation: campaign and group
This code returns only the relevant campaigns in the group.
$models = Campaigns::model()->with(array(
'Campgroupassoc' => array('condition' => "groupid=$id"),
))->findAll();
while this code:
$dataProvider = new CActiveDataProvider('Campaigns', array(
'criteria' => array(
'with' => array(
'Campgroupassoc' => array(
'condition' => "groupid=$id"
)
),
)
));
returns campaigns which are not in the same group..
What am i doing wrong?
Thx
'Campgroupassoc' => array(
'condition' => "groupid=:id",
'params'=>array(':id'=>$id)
)
Also it is better to specify to what model the groupid belongs to. And of course you can see what SQL dataprovider is generating and analize it.
Edit-----
After consulting with the Yii live chat, i found that even when using eager loading it will result in 2 queries instead of 1...
in order to solve this you need to add:
'together' => TRUE
I have developed API's with Zf2 and DynamoDB, I am able to get values from GET params in my local machine but unable to get values from GET params when I uploaded the API's in production
.
FYI: POST method is working properly in production.
Below is the controller get function.
public function get($id)
{
$abcModel = new ABCModel();
error_log("tournamentId:".$this->params()->fromQuery('tournamentId') );
$query = $this->getRequest()->getQuery();
error_log("tournamentId1:".$query['tournamentId']);
error_log("tournamentId2:".$this->getEvent()->getRouteMatch()->getParam('tournamentId'));
error_log("tournamentId3:".$this->params('tournamentId'));
error_log("tournamentId4:".$this->params()->fromRoute('tournamentId'));
}
I have tried all the answers of this question ZF2: Get url parameters in controller.
Can any one know what could be the reason for this?
Any light on the path would be helpful.
To use query string in the production environment, you have to use some alternate approach.
You can add parameter along with route to hold the query string value. But the query string needs to be passed using "/" mark between the route and query string instead of using "?" mark.
/route-name/key=value&key=value1
and the routing configuration need to be
'router' => array(
'routes' => array(
'<route-name>' => array(
'type' => 'segment',
'options' => array(
'route' => '<route-name>[/:action][/:queryPara][/]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'queryPara' => '[a-zA-Z][a-zA-Z0-9_-&=]*',
),
'defaults' => array(
'controller' => 'Application\Controller\Index',
'action' => 'index',
)
),
),
)),
You can create a function that will extract the query string and returns the array containing key=>value pairs of query string.
And in controller you have to call the function by passing the query string which will be stored in "/queryPara" part after the route name using the following statement you will get the string
$this->params('queryPara')
Hope it helps
Thanks
I have a Cake Application v2.3.1 running locally on mamp v2.1.3 (not pro so this is the latest version) from myapp.dev:port and I'm experiencing some really slow response when I have pagination on the site (about 5 seconds), here's my code in the controller:
public $paginate = array(
'fields' => array('Artist.id, Artist.year_born, Artist.year_died, Artist.country_born'),
'limit' => 50,
'order' => array('Artist.id' => 'desc')
);
I use the twitter bootstrap plugin for my pagination https://github.com/slywalker/TwitterBootstrap like this in AppController.php:
public $helpers = array('Paginator' => array('className' => 'TwitterBootstrap.BootstrapPaginator'));
I tried to set the limit of the pagination to 1 and also tried using cakes own pagination instead of bootstrap, but it's still really slow. I has to be something with the pagination because I can access an artist like myapp.dev:port/artists/view/14532 and that works good so I don't think it has anything to do with the sql query.
I tried around changing names in the /etc/hosts file 127.0.0.1 localhost myapp.dev and ::1 localhost myapp.dev but nothing seems to work. Any ideas? I'm really stuck.
Update: Feel a bit bad about not mentioning the hasMany relationship that my Artist table have. This is my Artist model:
class Artist extends AppModel {
public $hasMany = array(
'ArtistBiography' => array('dependent' => true),
'ArtistSurname' => array('dependent' => true),
'ArtistSignature' => array('dependent' => true),
'ArtistForename' => array('dependent' => true),
'ArtistMonogram' => array('dependent' => true));
public $hasOne = array(
'ArtistActive' => array('dependent' => true));
}
I used the DebugKit and I found that the paginator does 2 unnecessary querys for two left joins that both takes around 2000 ms each to execute. How can I tell the paginator to ignore this? I tried something like this to give a new relationship:
public $paginate = array(
'fields' => array('Artist.id, Artist.year_born, Artist.year_died, Artist.country_born'),
'limit' => 50,
'order' => array('Artist.id' => 'desc'),
'joins' => array(
array('table' => 'artist_forenames', 'alias' => 'ArtistForename', 'type' `=> 'inner', 'conditions' => array('Artist.id = ArtistForename.artist_id')),`
array('table' => 'artist_surnames', 'alias' => 'ArtistSurname', 'type' => 'INNER', 'conditions' => array('Artist.id = ArtistSurname.artist_id'))),
'recursive' => -1
);
But I'm not sure how to make this work. What I want basically is to join the artist_surnames and artist_fornames and ignore two tables called artist.actives and artist_monogram that both together slows down the query with 4000ms.
My second question here is why do these two joins slows it down so much? I did a test-view called artists/all where I'm listing 100 artists and there my query with all the joins is done in around 40-50ms.
TLDR:
Set $recursive to -1
Use CakePHP's Containable Behavior to only retrieve the associated data you want
Example of code:
//wherever you set this variable
$paginate = array(
'recursive' => -1,
'limit' => 50,
'order' => array('Artist.id' => 'desc'),
'contain' => array(
'ArtistSurname',
'ArtistForName'
)
);
Remember to look through the documentation for Containable - it explains how you set your Model(s) to $actsAs Containable, set recursive to -1...etc etc.
I suggest actually setting public $recursive=-1' and public $actsAs =array('Containable'); both in your AppModel - that way ALL models are set up and ready to go with Containable whenever you want. Also, anything higher than -1 for recursive is bad IMHO - Containable is so much better in every respect.
I have hasMany Through table which is Chats table with Chat model and I'm using loadModel in User controller to load Chat model then ran below query to bindModel with Chat.user_id and User.id :
$this->loadModel('Chat');
$this->Chat->bindModel(array(
'belongsTo' => array(
'User' => array(
'foreignKey' => false,
'conditions' => array('Chat.user_id = User.id')
)
)
));
$lastChat = $this->Chat->find('all', array(
'conditions' => array(
'Chat.receiver_id' => $user_id['User']['id']
),
'order' => array('Chat.id DESC'),
'fields' => array(
'Chat.id',
'Chat.chat',
'Chat.user_id',
'Chat.receiver_id',
'Chat.read',
'Chat.created'
),
'group' => array('Chat.user_id')
));
I want to join those tables together but this does not seem to work in Cake way I tried with normal SQL query and it works fine.
What could be wrong here?
Have you tried setting the recursive property before the find? Eg:
$this->Chat->recursive = 3;
You may need to set this after $this->Chat->bindModel, but I am not sure if this will make a difference or not. You will also need to re-bind the User model before each find, if, for example, your find queries are run within a loop ...
I am stuck on pagination in CakePHP 1.3. I am trying to paginate feePayment records based on certain criteria.
feePayments belongs to Students which in turn belongs YearGroups.
I want to paginate 'unpaid' feePayments for each year group. The problem I am having is that the SQL query seems to only take into account the conditions I specified for the FeePayment model and ignores the YearGroup criteria so only overdue unpaid records are returned regardless of the year group specified.
Here is my code:
function unpaidClass($id) {
$this->paginate = array(
'FeePayment' => array ('recursive' => 1, 'conditions' => array('FeePayment.status' => 'Unpaid', 'FeePayment.due_date <= ' => date("Y-m-d"))),
'YearGroup' => array ('recursive' => 1, 'conditions' => array('YearGroup.school_year' => $id))
);
$this->set('feePayments', $this->paginate());
}
Hope this makes sense, appreciate any help.
Thanks,
Sid.
You should consider using the Containable behavior. This behavior allows you to group the necessary data you want without relaying on the "recursiveness" of your query. You can place conditions on your contained data similar to the way you would in your queries and is a more permanent way to structure data across your application instead of specifying conditions over and over again in each query.
Paginate should automatically pick up these associations when you Paginate your main model. Here's an example of what I mean here: http://cakephp.1045679.n5.nabble.com/Paginate-with-Containable-td1300971.html#a1300971
These should make your task easier.
After a lot of searching the net and reading CakePHP's documentation, here is the solution I came up with:
function unpaidClass($id) {
$this->FeePayment->unbindModel(array(
'belongsTo' => array('Student')
), $reset = 0);
$this->FeePayment->bindModel(array(
'belongsTo' => array(
'Student' => array(
'foreignKey' => false,
'conditions' => array('Student.id = FeePayment.student_id')
),
'YearGroup' => array(
'foreignKey' => false,
'conditions' => array('YearGroup.id = Student.year_group_id')
)
)
), $reset = 0);
$this->paginate = array(
'contain' => array('Student','YearGroup'),
'conditions' => array('YearGroup.school_year' => $id,
'FeePayment.status' => 'Unpaid',
'FeePayment.due_date <= ' => date("Y-m-d")));
$this->set('feePayments', $this->paginate());
}