Rename a table in the controller by query - cakephp-3.0

I try to do a private message application with an user_id who send the message and a post_id who receive the message in the table.
I did the association on my table like this:
$this->belongsTo('receiver', [
'className' => 'Users',
'foreignKey' => 'post_id'
]);
$this->belongsTo('shipper', [
'className' => 'Users',
'foreignKey' => 'user_id'
]);
But now I need to merge these to get one 'interlocutor' in my request:
$messages = $this->Messages->find()->where(['post_id =' => $id])
->orWhere(['user_id =' => $id])->contain(['shipper','receiver']);
I know I have to filter with function in the contain to get only the shipper or the receiver who's not me but I don't know how to merge or simply rename 'shipper' and 'receiver' into 'interlocutor'.
All I did is working, btw.
I'm not that good in english so if you have a better title, let me know it
Thanks for help

I guess you need something like http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#custom-finder-methods
Example:
public function findInterlocutor(Query $query, array $options)
{
$query->contain(['shipper','receiver']);
return $query;
}
Calling it this way:
$messages = $this->Messages->find()->where(['post_id =' => $id])
->orWhere(['user_id =' => $id])->find('interlocutor');
Please let me know if it works...

Related

Associate tables from different database cakephp 3.0

I have two database with name default and default_history. And tables with name users and wafer_detail_history under default database and order_history under default_history database. want to associate Users table with OrderHistory table.
OrderHistoryTable :-
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('order_history');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->hasMany('WaferDetailHistory', [
'foreignKey' => 'order_id'
]);
$this->belongsTo('Users', [
'foreignKey' => 'created_by',
'joinType' => 'INNER'
]);
}
i used this.
$connection = ConnectionManager::get('default_history');
$this->OrderHistory = TableRegistry::get('OrderHistory');
$this->OrderHistory->setConnection($connection);
$id = 37;
$order_history = $this->OrderHistory->get($id, ['contain' => ['Users']]);
but not able to succeed. getting this error:
Base table or view not found: 1146 Table 'default_history.users'
doesn't exist
I had the same problem few days ago,
You must had 'strategy' => 'select' in your BelongTo to join with the other database
$this->belongsTo('Users', [
'strategy' => 'select'
'foreignKey' => 'created_by',
'joinType' => 'INNER'
]);
Try this on the OrderHistoryTable.php File:
$this->setTable('default_history.order_history');

Retrieve only necessary data

Here is my store function
public function store(Request $request)
{
$post = new Post();
$post->author()->associate(auth()->user());
$post->fill($request->all());
$post->save();
return response()->json($post);
}
As a response i get:
I don't want all the data so I tried to take only the data I have defined like this:
$post = $post->only([
'id',
'title',
'content',
'published_at',
'author'
]);
And response now is:
Much better, but not completely. I can not define post author data in this way.
The only way is by creating a creepy relationship where you select only necessary data or like this:
$post = [
'id' => $post->id,
'title' => $post->title,
'content' => $post->content,
'published_at' => $post->published_at->toDateTimeString(),
'author' => [
'id' => $post->author->id,
'name' => $post->author->name,
'email' => $post->author->email,
]
];
So my question is... maybe there is more elegant way to achieve this.
Thank you very much!
The simplest way would probably be to just use only with the author as well:
return $post->only('id', 'title', 'content') + [
'author' => $post->author->only('id', 'name', 'email'),
];
If it was going to get any more complicated or reused somewhere else then I would suggest using something like Eloquent Resources
I would add a function to your Post model
public function jsonOutput()
{
$array['id'] = $this->id;
$array['title'] = $this->title;
$array['content'] = $this->content;
$array['author'] = [
'id' => $this->author->id,
'name' => $this->author->id
];
return $array;
}
and then call it like this
return response()->json($post->jsonOutput());

Insert or update in laravel?

What would be the best way to set this query? i can't seem to find any documentation on an actual insert or update that works, I'm hoping to do it via the Eloquent model but can't seem to get it working
any help would be appreciated.
DB::table('questions')->insert([
'marital_status' => $request->marital_status,
'job_title' => $request->job_Title,
'industry' => $request->industry,
'occupation' => $request->occupation,
'paye' => $request->paye,
'self_employed' => $request->self_employed,
'child_benefit' => $request->child_benefit,
'work_home' => $request->work_home,
'own_transport' => $request->own_transport,
'company_vehicle' => $request->company_vehicle,
'annual_income' => $request->annual_income,
'pay_memberships' => $request->pay_memberships,
'income_benefits' => $request->income_benefits,
'printer' => $request->printer,
'contact' => $request->contact,
'share' => $request->share,
'terms' => $request->terms,
'user_id' => $user
]);
here is my Model for Questions
<?php
namespace App;
class Questions extends Model
{
protected $fillable = [
'marital_status',
'job_title',
'industry',
'occupation',
'paye',
'self_employed',
'child_benefit',
'work_home',
'own_transport',
'company_vehicle',
'annual_income',
'pay_memberships',
'income_benefits',
'printer',
'contact',
'share',
'terms',
'user_id'
];
public function users(){
return $this->hasOne('App\User');
}
}
Use Eloquent with mass assignment:
Question::updateOrCreate($request->all()->put('user_id', $user));
Or:
$question = Question::firstOrNew('some_id', $someId);
$question->fill($request->all()->put('user_id', $user))->save();
Don't forget to fill $fillable array with all properties you want to persist:
class Question extends Model
{
protected $fillable = [
'marital_status',
'job_title',
'industry',
'occupation',
'paye',
'self_employed',
'child_benefit',
'work_home',
'own_transport',
'company_vehicle',
'annual_income',
'pay_memberships',
'income_benefits',
'printer',
'contact',
'share',
'terms',
'user_id'
]
Update
If put() method doesn't work for some reason, try this:
$request->merge(['user_id' => $user]);
And then just use $request->all()
Or:
$requestData = $request->all();
$requestData['user_id'] = $user;
And then use $requestData

How to choose the fields from a associated model at find

Before I had this:
//ArticlesController::index
$articles = $this->Articles->find('all', [
'contain' => ['Comments']
]);
So I set the fields key:
//ArticlesController::index
$articles = $this->Articles->find('all', [
'fields' => ['title', 'text],
'contain' => ['Comments']
]);
Since I set the fields key the result of the find is not bringing the comments anymore.
$articles = $this->Articles->find('all')
->select(['fields_you_want_from_Articles'])
->contain(['Comments' => function($q) {
return $q
->select(['fields_you_want_from_Comments']);
}]);

CakePHP find Queries with aliases SQLSTATE[42S22] Error

I'm having a weird problem with my relationships/aliases in CakePHP and now its preventing me from accessing my data correctly.
I have:
User hasMany CreatorModule (alias for Module)
User HABTM LearnerModule (alias for Module)
Module belongsTo Creator (alias for User)
Module HABTM Learner (alias for User)
And I'm trying to call:
$id = $this->Module->User->findByEmail($email);
$modules = $this->Module->findByUserId($id['User']['id']);
The queries that get generated aren't correct - the table-alias is wrong. I'm not sure which of the above is responsible but I get:
SELECT
`Creator`.`id`,
`Creator`.`email`,
`Creator`.`organization`,
`Creator`.`name`,
`Creator`.`password`,
`Creator`.`verified`,
`Creator`.`vcode`
FROM
`snurpdco_cake`.`users` AS `Creator`
WHERE
`User`.`email` = 'foo#example.com' # <--
LIMIT 1
I figured out that the error is that CakePHP should change 'User' in the WHERE clause to Creator, but doesn't, even if I use the alias. How do I complete this query correctly.
Further, as a related problem, I find that I can no longer use User in my model calls etc now that I have defined aliases. Is there a way around this?
EDIT: As requested, here is my model code defining the aliases:
class User extends AppModel {
public $name = 'User';
public $uses = 'users';
public $hasMany = array(
'OwnedModule' => array(
'className' => 'Module',
'foreignKey' => 'user_id',
'dependent' => true
));
public $hasAndBelongsToMany = array(
'LearnerModule' => array(
'className' => 'Module',
'joinTable' => 'modules_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'module_id',
'unique' => 'keepExisting',
));
//The rest of the Model
}
//Different file, condensed here for spacing
class Module extends AppModel {
public $name = 'Module';
public $belongsTo = array(
'Creator' => array(
'className' => 'User'));
public $hasAndBelongsToMany = array(
'Learner' => array(
'className' => 'User',
'joinTable' => 'modules_users',
'foreignKey' => 'module_id',
'associationForeignKey' => 'user_id',
'unique' => 'keepExisting',
));
//The rest of the Model
}
try
$id = $this->Module->Creator->find('first',
array('conditions' => array('Creator.email' => $email)
);
$modules = $this->Module->findByCreatorId($id['User']['id']);