Doctrine and MySQL - 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');
}
}

Related

How to chain with clauses in Laravel

I've a User model which have many Orders (Order model), and each Order belongs to a Translator (Translator Model).
The behavior that I'm trying to reach is when I fetch a User by his Id, I want to get his orders and the translator associated with each order.
I try to use this code: $user = User::where('id', $id->id)->with('orders')->with('translator')->get();, I expect that it will return the proper data which should be something like this:
{
...user data,
orders: [
{
...order_data,
translator: {
...translator_data
}
}
]
}
but that doesn't work.
Is there anyway to get this behavior in Laravel ?
You can eager load nested relationships using the . to distinguish this:
$user = User::where('id', $id->id)->with('orders.translator')->first();
// or
$user = User::with('orders.translator')->find($id->id);
Side Note, if $id is a User instance you can Lazy Eager Load the relationship on it:
$id->load('orders.translator');
Laravel 7.x Docs - Eloquent - Relationships - Eager Loading - Nested Eager Loading with
Laravel 7.x Docs - Eloquent - Relationships - Eager Loading - Lazy Eager Loading load

Disable Doctrine automatic queries

With Symfony 4.2 and Doctrine, I want to disable automatic queries.
If I execute this simple example :
$posts = $em->getRepository(Post::class)->findAll();
foreach ($posts as $post) {
dump($post->getCategory()->getName();
}
Doctrine will search categories by itself. But I want to disable that. to force me to join (LEFT or INNER in repository).
It's possible ? Thanks
Implicit data fetching from database by accessing linked entity properties is one of core principles of Doctrine and can't be disabled. If you want to just fetch some data explicitly - you need to construct your own partial query and hydrate data either as array or simple object so your fetched results will not became entities.
Nothing can automatically disable this behavior and force you to write JOIN clauses, except your wishes.
This behavior (which is called lazy loading) is one of the main common behavior of all ORMs.
If you are not happy with this (and you probably have good reasons), then consider writing your own DQL queries, which are limited to your selected fields. What is not in your query will not be fetched automatically afterwards.
Write this method in your custom PostRepository class :
public function findAll(){
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('p')
->from('Post', 'p');
return $qb->getQuery()->getResult();
}
Then in your controller, you can do the same as before:
$posts = $em->getRepository(Post::class)->findAll();
foreach ($posts as $post) {
dump($post->getCategory()->getName();
}
Calling the getName() method from the Category entity will now throws an error, and will not launch any hidden SQL queries behind. If you want to play with Posts and Categories together, then you can adapt your findAll() method like this :
public function findAll(){
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('p, c')
->from('Post', 'p');
->join('p.category', 'c')
return $qb->getQuery()->getResult();
}

cakephp3 own query builder

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)

Use MYSQL AES_DECRYPT function in eloquent?

I am using Slim Framework with eloquent ORM for database operations, I want to store encrypted data in the database(MYSQL) for fewer columns of particular tables.
I have tried with AES_ENCRYPTin eloquent model which stored the data well with mutators like,
class MyDataModel extends Model {
public function setProcessDataAttribute($value)
{
$this->attributes['process_data'] =
DB::raw("AES_ENCRYPT('".$value."', '12345')");
}
}
Now, I want to decrypt with the MYSQL function AES_DECRYPT, is there any way to use MYSQL functions in the eloquent model?
I am not sure how can I override the find, get methods in my model.
In laravel 5, recommend use his AES encryption:
$newEncrypter = new \Illuminate\Encryption\Encrypter('your key or app_key#env', config('app.cipher') );
$decrypted = $newEncrypter->decrypt('your encrypted data');

Making PDO Database Connection available in controllers and models

right now, I am kinda frustrated and I hope someone can help me and point me into the right direction.
I have an "old" project which uses the mysql statements for connection to database, etc.
Within this project I have the following:
An index file containing
*
* load configuration and connect to database
*/
$projectConfiguration = new projectConfiguration();
$dbconnect = $projectConfiguration->connect($projectConfiguration->databaseHost, $projectConfiguration->databaseName, $projectConfiguration->databaseUser, $projectConfiguration->databasePass);
// load controller
$ReqMod = FatFramework\Functions::getRequestParameter("mod");
if (!$ReqMod) {
$ReqMod = FatFramework\Functions::getRequestParameter("controller");
}
$module = ($ReqMod) ? $ReqMod : 'default';
In this style I call the views and actions in classes, like SaveAction()
Using mysql always made it very simple to use this database connection in the models called by the controllers like
public function loadCustomersList($sAdditionalWhere = false)
{
$sQuery = "SELECT * FROM customers WHERE 1 ";
if ($sAdditionalWhere) {
$sQuery .= "AND " . $sAdditionalWhere . " ";
}
$sQuery .= "ORDER BY company";
$sql = mysql_query($sQuery);
while (($customer = mysql_fetch_object($sql)) != false) {
$aCustomers[] = $customer;
}
return $aCustomers;
}
I want to totally refractor this project and use PDO. I tried for the last 4 hours to find a solution, but I can't figure out how to make it work.
I think I don't need an extra dbconnect class since PDO is a class itself, am I right?
In the new index file I tried the following:
$db = new database();
try{
$dbc = new PDO($db->get_DbConSettings());
$dbc->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}catch(PDOException $e)
{
echo 'Verbindung fehlgeschlagen: '.$e->getMessage();
}
But with this $dbc will not available in controllers or models. It there a way to make it available there? If not, what is the best solution?
Do I have to make a database connection in every model?
An other issue I have with this is:
$db->get_DbConSettings()
in
$dbc = new PDO
gives back
'mysql:host=127.0.0.1; dbname=c1virtbkk', 'root', '123'
($dbc = new PDO('mysql:host=127.0.0.1; dbname=c1virtbkk', 'root', '123');)
I cannot connect to the database. I get the following:
Verbindung fehlgeschlagen: could not find driver
If I don't use $db->get_DbConSettings and put the required information manually in, I don't get any error and can do queries. Any hints?
Help is really appreciated.
Thanks in advance!
Mark
Definitely don't create a new PDO connection in each model. Creating MySQL database connections is fairly quick, but there's still some overhead to doing so. You want to reuse a connection throughout your request. If nothing else, it allows you to share a transaction across multiple models.
Some frameworks store shared resource objects in a "registry" class which is a singleton key-value store. It's not really much more than a global hash array, but making it a class makes the registry itself more easily tested with PHPUnit. See https://framework.zend.com/manual/1.12/en/zend.registry.using.html for an example of a registry.
You're right that PDO is a class, even though it's implemented as a C extension instead of a PHP class. But it's a class, and new PDO(...) returns an object of that class.
One reason to create a db class of your own is to help you in unit-testing, because you could create a mock object for your db class so you can test your other classes (even model classes) without needing a live database connection. Your db class could extend or else contain a PDO object.
Your issue about the error "could not find driver" is probably because the PDO driver for mysql is not installed. PDO is one PHP extension, and then there's a separate extension for each brand of SQL database. You can confirm this with:
$ php -i
...lots of output...
PDO
PDO support => enabled
PDO drivers => mysql, odbc, sqlite
pdo_mysql
PDO Driver for MySQL => enabled
Client API version => mysqlnd 5.0.11-dev - 20120503 - $Id: 76b08b24596e12d4553bd41fc93cccd5bac2fe7a $
...more output for other extensions...
Note that PDO tells me which drivers I have installed: mysql, odbc, and sqlite.
So you need to install pdo_mysql. I'm not sure what OS you're on, but I'm often on CentOS Linux or Ubuntu Linux. The pdo_mysql is available as a separate package via yum or apt.
Re your comment:
Okay, here's an example of a registry:
class registry {
protected static $items = array();
public static get($key) {
return isset(self::$items[$key])?
self::$items[$key] : null;
}
public static set($key, $object) {
self::$items[$key] = $object;
}
}
In your controller initial code, you'd create a database object and store it in the registry:
$projectConfiguration = new projectConfiguration();
$dbconnect = $projectConfiguration->connect(
$projectConfiguration->databaseHost,
$projectConfiguration->databaseName,
$projectConfiguration->databaseUser,
$projectConfiguration->databasePass);
registry::set('db', $dbconnect);
Then in your model class methods (or anywhere you need the database), get the db object from the registry and use it:
public function loadCustomersList($sAdditionalWhere = false)
{
$sQuery = "SELECT * FROM customers WHERE 1 ";
if ($sAdditionalWhere) {
$sQuery .= "AND " . $sAdditionalWhere . " ";
}
$sQuery .= "ORDER BY company";
$db = registry::get('db');
$stmt = $db->query($sQuery);
$aCustomers = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $aCustomers;
}