i create a query like below but always error Not unique table/alias although i add alias for askPo in every relation model.
$query = AskPolicy::find();
$query-> JoinWith(['askPos'])
->where(['askPolicy.id' => 'askPos.id_policy'])
->innerJoinWith(['askPos.askGoods'])
->andWhere('ask_po.id = ask_goods.id_po')
->innerJoinWith(['askTransports'])
->andWhere('ask_policy.id = ask_transport.id_po')
->innerJoinWith(['client'])->andWhere(['id_client'=>Yii::$app->user->identity->id_client])->all();
below i have add alias
model a :
public function getAskPos()
{
return $this->hasMany(\frontend\modules\ask_marine_cargo\models\AskPo::className(), ['id_policy' => 'id'])->from(AskPo::tableName() . ' askPo1');;
}
model b :
public function getPo()
{
return $this->hasOne(\frontend\modules\ask_marine_cargo\models\AskPo::className(), ['id' => 'id_po'])->from(AskPo::tableName() . ' getPo');
}
SQL query :
SELECT
ask_goods.name,
ask_po.po_num,
ask_policy.policy_num,
ask_transport.type_transport
FROM ask_policy
INNER JOIN ask_po
ON ask_po.id_policy = ask_policy.id
INNER JOIN ask_goods
ON ask_po.id = ask_goods.id_po
INNER JOIN ask_transport
ON ask_policy.id = ask_transport.id_po;
Related
I have a table named purchase_details in where during purchase, I am storing many items' purchase record at a time. During purchase also I am updating items table column opening_balance based on purchased items id, Now I am getting trouble when trying to sum 'purchase details' table quantity's value with 'items' table old opening_balance - in the controller, I am trying something like this-
public function store(Request $request)
{
$grandTotal = $request->input('grand_total');
$paidAmount = $request->input('paid_amount');
$purchase = new Purchase;
$purchase->no = $request->input('no');
$purchase->purchase_date = Carbon::parse($request->purchase_date)->format('Y-m-d');
$purchase->notes = $request->input('notes');
$purchase->supplier_id = $request->input('supplier');
$purchase->total_quantity = $request->input('total_quantity');
$purchase->grand_total = $grandTotal;
$purchase->paid_amount = $paidAmount;
$purchase->due_amount = abs($grandTotal - $paidAmount);
$purchase->save();
$itemDetails = [];
$itemIds = $request->input('itemIds');
$itemQuantities = $request->input('itemQuantities');
$itemPrices = $request->input('itemPrices');
$itemTotals = $request->input('itemTotals');
$orderNotes = $request->input('orderNotes');
foreach ($itemTotals as $key => $total) {
$itemDetails[] = [
'item_id' => $itemIds[$key],
'quantity' => $itemQuantities[$key],
'unit_price' => $itemPrices[$key],
'total_price' => $itemTotals[$key],
];
$openingBalance = Item::where('id', $itemIds[$key])->get(['opening_balance']);
DB::table('items')
->where('id', $itemIds[$key])
->update(['opening_balance' => $openingBalance + $itemQuantities[$key]]);
}
$purchase->purchaseDetails()->createMany($itemDetails);
return back();
}
You use collection as int, edit your code:
$openingBalance = Item::select(['opening_balance'])->where('id', $itemIds[$key])->first()->opening_balance;
Note : I have not shared database schema as I am mainly looking for a help only w.r.t. last step which is 'left outer join' on 2 sub-queries.
select *
from
(select id
from Action
where id = 3) AS act1
left Outer Join
(select Action.name,
completed_At as completedAt,
deadline, notes,
ActionAssignedTo.action_Id as actionId,
from Action
inner join Employee
on Action.created_By_Id = Employee.id
and Employee.vendor_Id = 2
inner join ActionAssignedTo
on Action.id = ActionAssignedTo.action_Id
and ActionAssignedTo.action_Id = 3
where Action.created_By_Id = 7
group by Action.id
limit 2) AS act2
on act1.id = act2.actionId
I need to write this above query using Bookshelf
let options = {columns: [ 'Action.name', 'completed_At as completedAt',
'deadline', 'notes',
'ActionAssignedTo.action_Id as actionId',
]};
let action2 = new Action();
action2.query().innerJoin('Employee', function () {
this.on('Action.created_By_Id', 'Employee.id')
.andOn('Employee.vendor_Id', bookshelf.knex.raw(1));
});
action2.query().innerJoin('ActionAssignedTo', function () {
this.on('Action.id', 'ActionAssignedTo.action_Id')
.andOn('ActionAssignedTo.action_Id', bookshelf.knex.raw(5));
});
action2.query().where(function() {
this.where('Action.created_By_Id', empId)
});
action2.query().groupBy('Action.id');
action2.query().limit(2);
action2.query().columns(options.columns);
let action1;
action1 = Action.where('id', actionId);
action1.query().columns('id');
return bookshelf.knex.raw('select * from '
+ '(' + action1.query().toString() + ') AS act1'
+ ' left Outer Join '
+ '(' + action2.query().toString() + ') AS act2'
+ ' on act1.id = act2.actionId');
I am not keen on using bookshelf.knex.raw for using the left Outer Join as the output given by knex.raw and bookshelf differ.
Is there a way I can do the 'left Outer Join' directly using bookshelf library.
I looked into the code but it seems leftOuterJoin only takes table name as the first parameter and what I need is a query.
I think your main problem is that you're using Bookshelf like you would be using knex. Bookshelf is meant to be used with models you would define and then query on them.
Here is an example of what you should have as model
// Adding registry to avoid circular references
// Adding camelcase to get your columns names converted to camelCase
bookshelf.plugin(['bookshelf-camelcase', 'registry']);
// Reference: https://github.com/brianc/node-pg-types
// These two lines convert all bigint values coming from Postgres from JS string to JS integer.
// Removing these lines will mess up with Bookshelf count() methods and bigserial values
pg.types.setTypeParser(20, 'text', parseInt);
const Action = db.bookshelf.Model.extend({
tableName: 'Action',
createdBy: function createdBy() {
return this.belongsTo(Employee, 'id', 'created_By_Id');
},
assignedTo: function assignedTo() {
return this.hasMany(ActionAssignedTo, 'action_id');
},
});
const Employee = db.bookshelf.Model.extend({
tableName: 'Employee',
createdActions: function createdActions() {
return this.hasMany(Action, 'created_By_Id');
},
});
const ActionAssignedTo = db.bookshelf.Model.extend({
tableName: 'ActionAssignedTo',
action: function action() {
return this.belongsTo(Action, 'id', 'action_Id');
},
employee: function employee() {
return this.belongsTo(Employee, 'id', 'employee_Id');
},
});
module.exports = {
Action: db.bookshelf.model('Action', Action),
Employee: db.bookshelf.model('Employee', Employee),
ActionAssignedTo: db.bookshelf.model('ActionAssignedTo', ActionAssignedTo),
db,
};
You would then be able to fetch your results with a query like this
const Model = require('model.js');
Model.Action
.where({ id: 3 })
.fetchAll({ withRelated: ['createdBy', 'assignedTo', 'assignedTo.employee'] })
.then(data => {
// Do what you have to do
});
What your want to achieve is not possible with only one query in Bookshelf. You probably need to do a first query using knex to get a list of Action ids and then give them to Bookshelf.js
db.bookshelf.knex.raw(`
select ActionAssignedTo.action_Id as actionId,
from Action
inner join Employee
on Action.created_By_Id = Employee.id
and Employee.vendor_Id = ?
inner join ActionAssignedTo
on Action.id = ActionAssignedTo.action_Id
and ActionAssignedTo.action_Id = ?
where Action.created_By_Id = ?
group by Action.id
limit ?`,
[2, 3, 7, 2]
)
.then(result => {
const rows = result.rows;
// Do what you have to do
})
And then use the recovered Ids to get your Bookshelf query like this
Model.Action
.query(qb => {
qb.whereIn('id', rows);
})
.fetchAll({
withRelated: [{
'createdBy': qb => {
qb.columns(['id', 'firstname', 'lastname']);
},
'assignedTo': qb => {
qb.columns(['action_Id', 'employee_Id']);
},
'assignedTo.employee': qb => {
qb.columns(['id', 'firstname', 'lastname']);
},
}],
columns: ['id', 'name', 'completed_At', 'deadline', 'notes']
})
.fetchAll(data => {
// Do what you have to do
});
Note that the columns used for joins MUST BE in the columns list for each table. If you omit the columns, all the columns will be selected.
By default, Bookshelf will retrieve all columns and all root objects. The default is kind of LEFT OUTER JOIN.
I am working in Laravel5.4. I have created 3 table's.
User table :
tickets table :
ticket_cc_users table :
Now, I have create relation ship between users and tickets module like below.
User model :
public function tickets()
{
return $this->belongsToMany('App\User', 'ticket_cc_users', 'user_id', 'ticket_id');
}
Ticket model :
public function users()
{
return $this->belongsToMany('App\Models\Tickets\Ticket', 'ticket_cc_users', 'ticket_id', 'user_id');
}
TicketController controller save method :
public function store(Request $request)
{
return $request->all();
$ticket = new Ticket;
$ticket->requester_id = $this->user['id'];
//$ticket->assignee_id = $request->assignee_id;
//$ticket->cc_id = $request->cc_id;
$ticket->type = $request->type;
$ticket->priority = $request->priority;
$ticket->subject = $request->subject;
$ticket->description = $request->description;
$ticket->status = $request->status;
if($request->link)
{
$ticket->link = $request->link;
$ticket->due_date = null;
}
if($request->due_date && $request->due_date !="")
{
$ticket->due_date = date('Y-m-d',strtotime($request->due_date));
$ticket->link = "";
}
if($ticket->save())
{
$ticket->users()->sync($request->cc_id);
foreach($request->ticket_tags as $value){
$tag = new Tag;
$tag->tag_name = $value['text'];
$tag->save();
$ticketTag = new TicketTag;
$ticketTag->tickets_id = $ticket->id;
$ticketTag->tags_id = $tag->id;
$ticketTag->save();
}
$data = Ticket::find($ticket->id);
Mail::to('khyati#infirays.com')->send(new CreateTicket($data));
$response = array(
'success' => true
);
}
return $response;
}
Here, I am going to store data into ticket table. So I need to store cc user data into ticket_cc_user table. So how can I store ticket_id and user_id into this table. Here, I can get multiple user_id. And I am using Eloquent ORM.
Here, It gives an error like SQLSTATE[42S22]: Column not found: 1054 Unknown column '$$hashKey' in 'field list' (SQL: insert into ticket_cc_users ($$hashKey, address, city_id, country_id, created_at, deleted_at, email, firstname, id, introducer_id, is_verified, lastname, phone, signature, state_id, ticket_id, updated_at, user_id, username, userrole_id) values (object:109, , , , 2017-02-10 05:26:01, , nisarg.b#infirays.com, , 26, 1, , , 9999999999, , , 1, 2017-02-14 08:33:18, 0, nisarg, 2))
So,what code should I have to change in save function to store data into ticket_cc_users table?
It seems that belongsToMany() parameters order should be changed. The first and the last(4-th) parameters should be "about" same instance.
UPDATE Also the body of tickets() and users() functions should be exchanged
So try this:
User model :
public function tickets()
{
return $this->belongsToMany('App\Models\Tickets\Ticket', 'ticket_cc_users', 'user_id', 'ticket_id');
}
Ticket model :
public function users()
{
return $this->belongsToMany('App\User', 'ticket_cc_users', 'ticket_id', 'user_id');
}
From Laravel Many To Many Docs:
The third argument is the foreign key name of the model on which you are defining the relationship, while the fourth argument is the foreign key name of the model that you are joining to:
return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
I have two tables Project and User and a join table ProjectUser. I am creating a query to select the users under a certain projectName I couldn't do that so I created a query to select the id of the project according to its name from the project table
public function findName($projectName){
$query=$this->getEntityManager()
->createQuery("SELECT p.id FROM SocialProProjectBundle:Project p WHERE ``p.name='$projectName'");
return $query->getResult();
}
and then a query to select the users through the project id
public function findProjectUsers($pId){
$query=$this->getEntityManager()
->createQuery(
"SELECT pu, u FROM SocialProProjectBundle:ProjectUser pu JOIN SocialProDefaultBundle: User u WHERE pu.project = '$pId'"
);
return $query->getResult();
}
but I always get Notice: Array to string conversion !!!!!
Here is how I called them in the controller
$projectName = $request->get('projectName');
echo($projectName);
$projectId=$this->getDoctrine()->getRepository('SocialProMeetingBundle:meetingUser')->findName($projectName);
echo(count($projectId));
foreach($projectId as $pId) {
$pus = $this->getDoctrine()->getRepository('SocialProMeetingBundle:meetingUser')->findProjectUsers($pId);
}
$response = "<select class=\"select2_multiple form-control\" multiple=\"multiple\">";
foreach ($pus as $user) {//($i=0;$i<count($pus);$i++)
$name[]=array($user->getFirstName());
}
$response = $response . "<option>$name</option>";
$response = $response."</select> ";
return new Response($response);
//return($pus);
//call repository function
}
Hi: for the for loop question you had on how to solve it, use this code:
$response = "<select class=\"select2_multiple form-control\" multiple=\"multiple\">";
foreach($pus as $user){
$response . "<option>" . $user->getFirstName() . "</option>";
}
$response = $response."</select> ";
The solution I found to this is that I avoided the $pId and found the query capable to select the users through the $projectName Here it Is :
public function findProjectUsers($projectName){
$query=$this->getEntityManager()
->createQuery(
"SELECT u.firstName FROM SocialProDefaultBundle:User u, SocialProProjectBundle:Project p, SocialProProjectBundle:ProjectUser pu WHERE u.id = pu.user AND p.id=pu.project AND p.name='$projectName'");
return $query->getResult();
}
I can't get fields from the joined table. Here is my situation, I have two tables called "query" and "region" handeled by two controllers QueryCOntroller and RegionController. From the QueryController I tried to join the "query" to "region". to get the name of "query"'s "region"'s name in a view file but I can't get the desired field
public function fetchMine($myid)
{
$sql = new Sql( $this->tableGateway->adapter ) ;
$where = new Where() ;
$where->equalTo('agent_id', $myid) ;
$select = $sql->select() ;
$select -> from ( $this->tableGateway->getTable() )
-> join ( 'region' , 'query.agent_id = region.id')
->columns(array('*'))
-> where( $where ) ;
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet;
}
in my Module.php, getServiceConfig()
'Management\Model\QueryTable' => function($sm) {
$tableGateway = $sm->get('QueryTableGateway');
$table = new QueryTable($tableGateway);
return $table;
},
'QueryTableGateway' => function ($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Query());
return new TableGateway('query', $dbAdapter, null, $resultSetPrototype);
},
try:
public function fetchMine($myid)
{
$select = new Select ();
$select->from ( $this->tableGateway->getTable() );
$select->join ( 'region' , 'query.agent_id = region.id' , Select::SQL_STAR , Select::JOIN_LEFT )
$select->where( array( 'agent_id'=>$myid ) );
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet;
}
then you must extends Query from Region for getting all attributes of query and region,
Query.php:
use Management\Model\Region;
class Query extends Region
{
//...
}
The Query class must have attribute has the same name of region name in region table
if you want to use another name just use sql alias
if you want to add more attributes from region table you must add them all in Query class