cakephp3 own query builder - mysql

i'm new in cakephp, and i'm following the toutorial, i came from other languages and is not usual for me to read query like this:
public function findTagged(Query $query, array $options)
{
$columns = [
'Articles.id', 'Articles.user_id', 'Articles.title',
'Articles.body', 'Articles.published', 'Articles.created',
'Articles.slug',
];
$query = $query
->select($columns)
->distinct($columns);
if (empty($options['tags'])) {
// If there are no tags provided, find articles that have no tags.
$query->leftJoinWith('Tags')
->where(['Tags.title IS' => null]);
} else {
// Find articles that have one or more of the provided tags.
$query->innerJoinWith('Tags')
->where(['Tags.title IN' => $options['tags']]);
}
return $query->group(['Articles.id']);
}
This is a simple query and it's easy to understand ,but if i have a more complex query with a lot of join etc, is there the possibility to write your own query with sql sintax, can you help me translating this code to a query written in sql?
Thanks

You can write directly execute an SQL query with $connection->execute() (https://book.cakephp.org/3.0/en/orm/database-basics.html#running-select-statements) but I would recommend to stick to cakephp's ORM.
If you want to know how the query that you posted above translates into SQL, I would recommend to use the DebugKit. If you have in your app configuration debug = true, you will see this red rectangle at the bottem right corner, when you open your app in the browser. Click on it and click on "Sql queries": you will find the generated SQL from the query above somewhere in there. Alternatively you could use query logging (see here: https://book.cakephp.org/3.0/en/orm/database-basics.html#database-query-logging)

Related

How can I have the name of my entity instead of the id in the related tables

I'm creating a project on CakePHP 3.x where I'm quite new. I'm having trouble with the hasMany related tables to get the name of my entities instead of their ids.
I'm coming from CakePHP 2.x where I used an App::import('controller', array('Users') but in the view to retrieve all data to display instead of the ids, which is said to be a bad practice. And I wouldn't like to have any code violation in my new code. Can anybody help me? here is the code :
public function view($id = null)
{
$this->loadModel('Users');
$relatedUser = $this->Users->find()
->select(['Users.id', 'Users.email'])
->where(['Users.id'=>$id]);
$program = $this->Programs->get($id, [
'contain' => ['Users', 'ProgramSteps', 'Workshops']
]);
$this->set(compact('program', 'users'));
$this->set('_serialize', ['ast', 'relatedUser']);
}
I expect to get the user's email in the relatedUsers of the program table but the actual output is:
Notice (8): Trying to get property 'user_email' of non-object [APP/Template\Asts\view.ctp, line 601].
Really need help
Thank you in advance.
You've asked it to serialize the relatedUser variable, but that's for JSON and XML views. You haven't actually set the relatedUser variable for the view:
$this->set(compact('program', 'users', 'relatedUser'));
Also, you're setting the $users variable here, but it's never been initialized.
In addition to #Greg's answers, the variable $relateduser is still a query object, meaning that trying to access the email property will fail. The query still needs to be executed first.
You can change the query to:
$relatedUser = $this->Users->find()
->select(['Users.id', 'Users.email'])
->where(['Users.id' => $id])
->first();
Now the query is executed and the only the first entry is returned.
There is are a number of ways to get a query to execute, a lot of them are implicit is use. See:
Cookbook > Retrieving Data & Results Sets

How to compare two fields/columns in a condition?

I am having a hard time trying to figure out how to get a sub-query working.
Imagine I have:
$schools
->select($this->Schools)
->select([
'pupilcount' => $this->Pupils
->find()
->select([
$this->Pupils->find()->func()->count('*')
])
->where([
'Pupils.school_id' => 'Schools.id',
]),
The problem I am experiencing (I think) is that Schools.id is always 0 and so the count is returned as 0. I can pull out the Pupils join and it shows Pupils there.
I tried changing my code to add a:
->select(['SCID' => 'Schools.id'])
and reference that in the sub-query but doesn't work, it will always return 0 for the pupilcount.
What am I doing wrong here?
Whenever encountering query problems, check what queries are actually being generated (for example using DebugKit). Unless being an expression object, the right hand side of a condition will always be bound as a parameter, ie you're comparing against a string literal:
Pupils.school_id = 'Schools.id'
Generally for proper auto quoting compatibility, column names should be identifier expressions. While the left hand side will automatically be handled properly, the right hand side would require to be handled manually.
In your specific case you could easily utilize QueryExpression::equalFields(), which is ment for exactly what you're trying to do, comparing fields/columns:
->where(function (\Cake\Database\Expression\QueryExpression $exp, \Cake\ORM\Query $query) {
return $exp->equalFields('Pupils.school_id', 'Schools.id');
})
It's also possible to create identifier expressions manually by simply instantiating them:
->where([
'Pupils.school_id' => new \Cake\Database\Expression\IdentifierExpression('Schools.id')
])
or as of CakePHP 3.6 via the Query::identifier() method:
->where([
'Pupils.school_id' => $query->identifier('Schools.id')
])
And finally you could also always pass a single string value, which is basically inserted into the query as raw SQL, however in that case the identifiers will not be subject to automatic identifier quoting:
->where([
'Pupils.school_id = Schools.id'
])
See also
Cookbook > Database Access & ORM > Query Builder > Advanced Conditions
API > \Cake\Database\Expression\QueryExpression::equalFields()
API > \Cake\Database\Expression\IdentifierExpression

How to modify the output of a view in Drupal 7.x using a module

I want to modify the query that is running to create a table in a view but am having a hard time, so to keep it simple I am using a plain view that just lists users in a table and am trying to modify the query to make the table have two columns. I have been looking at the documentation for Drupal queries, trying to find tutorials, and looking at blog posts on how others modified queries in Drupal and Views, but so far none have worked or shown how to do something as simple as this, or I've tried to create simple query statements following what they did with no outcome.
I've mainly been trying to use hook_views_pre_execute() but have also tried . This is what my code looks like at the moment:
<?php
/**
* Implements hook_views_query_alter().
*/
// This function is called right before the execute process.
function my_module_views_pre_execute(&$view) {
if ($view->name == 'page' && $view->current_display == 'page') { //checks name of the view and what type it is
drupal_set_message("I can make changes to the view here.."); //diagnostic information, shows we can make changes to that view
$query =db_select('node','n')//select base table, alias is n.
->fields('n',array('nid', 'title', 'created', 'uid')); //adding fields nid, title, created, uid.
dpm($query->execute()->fetchAll()); // diagnostic information, shows whats being returned by the query
$query->execute()->fetchAll();
$view->build_info['query'] = $query;
}
}
I am able to create a message on the view with drupal_set_message("I can make changes to the view here..");, and in the Views settings tab I enabled 'Show the SQL query' and the output of that is the query from my module/code (it doesn't match the table created by Views).
So why doesn't it affect the table output at all? How do I modify what query is being run to display the view (which is apparently different from the 'Show the SQL query' output)?
I have taken example only for nid here I can provide you just an Idea for alter the views output.
/**
*
* #param type $view
* #param type $query
* Implements hook_views_query_alter(). This function is Used when we need to Alter the query before executing the query.
*/
function mymodule_views_query_alter(&$view, &$query) {
if ($view->name == 'VIEW_NAME' && $view->current_display == 'PAGE_NAME') {
drupal_set_message("I can make changes to the view here.."); //diagnostic information, shows we can make changes to that view
$query =db_select('node','n')//select base table, alias is n.
->fields('n',array('nid', 'title', 'created', 'uid')); //adding fields nid, title, created, uid.
dpm($query->execute()->fetchAll()); // diagnostic information, shows whats being returned by the query
$result = $query->execute()->fetchAll();
$nids = array();
foreach ($result as $value) {
$nids[] = $value->nid;
}
$view->query->where[1]['conditions'][] = array('field' => "node.nid", "value" => $nids, "operator" => "IN");
}
}
hook_views_pre_execute() is too late in the query build processs so I think you should use hook_views_query_alter().
Thanks

Laravel multiple column eloquent search query

i am very new in Laravel,currently working with Laravel4.I am trying to add a multiple column search functionality in my project.I can do single column eloquent search query,But honestly i have no idea how to do multiple column eloquent search query in laravel.I have two drop down menu
1.Locatiom
2.blood group.
i want to search an user having certain blood group against certain location.That is, user will select a location and blood group from those two drop down menu at a time and hit the search button.
In my database,i have two column, one contains the location and another contains the blood group of a certain user. Now,what should be the eloquent query for such a search?
Simply chain where for each field you need to search through:
// AND
$results = SomeModel::where('location', $location)->where('blood_group', $bloodGroup)->get();
// OR
$results = SomeModel::where('location', $location)->orWhere('blood_group', $bloodGroup)->get();
You can make it easier to work with thanks to the scopes:
// SomeModel class
public function scopeSearchLocation($query, $location)
{
if ($location) $query->where('location', $location);
}
public function scopeSearchBloodGroup($query, $bloodGroup)
{
if ($bloodGroup) $query->where('blood_group', $bloodGroup);
}
// then
SomeModel::searchBloodGroup($bloodGroup)->searchLocation($location)->get();
Just a sensible example, adjust it to your needs.
This is a great way but I think there is an error somewhere as laravel would not allow you to access a non-static function so instead of using
SomeModel::searchBloodGroup($bloodGroup)->searchLocation($location)->get();
you could simply use
SomeModel::BloodGroup($bloodGroup)->Location($location)->get();
take note of the searchBloodGroup has been changed to BloodGroup, that's how you will use it for all others also.
$errors = $connection->table('test_sessions_table')
->where('user_id', $user->id)
->where('status_question', 'false')->count('status_question');
in this method your code takes the following form
SQL code
select count(`status_question`) as aggregate from `test_sessions_table` where `user_id` = ? and `status_question` = ?
orWhere your code will look like this
$errors = $connection->table('test_sessions_table')
->where('user_id', $user->id)
->orWhere('status_question', 'false')->count('status_question');
SQL code
select count(`status_question`) as aggregate from `test_sessions_table` where `user_id` = ? or `status_question` = ?
Personally, I recommend using two ‘where’

Doctrine and MySQL

I have few questions about Doctrine and MySQL working together. I don't understand it in 100%
I read somewhere that Doctrine can cooperate with MySQL DB. How it happens?
How do I load my DB?
How do I operate on my MySQL tables via doctrine (I'm no thinking about creating new ones)?
Does Doctrine save automatically changes to database?, if not then how to?
Some sample of code would be great. I don’t care too much about language can be in PHP, Yaml and others.
a) please specify more what you maen with "load DB". Doctrine is an ORM.
check here docs:
http://www.doctrine-project.org/projects/orm/1.2/docs/hu (check cookbook)
b) operations with tables with Doctrine are with DQL, example:
$q = Doctrine_Query::create()
->from('User u')
->leftJoin('u.Phonenumbers p');
$q->execute(); //you get a doctrine collection to iterate results of query
c)NO you need to save the object
$account = new Account();
$account->name = 'test 1';
$account->amount = '100.00';
$account->save();
here is account class
class Account extends Doctrine_Record
{
public function setTableDefinition()
{
$this->hasColumn('name', 'string', 255);
$this->hasColumn('amount', 'decimal');
}
}