I have an array $brands as parameter of my repository function public function getBrandsByFilter($brands). I rescue this array from an ajax POST method and it looks like at :
$brands = ["brand"
[
"caporal" => "caporal"
"adidas" => "adidas"
]
]
I'd like to pass each values (caporal, adidas) of my array as arguments of my WHERE query clause of my repository but I have this exception :
An exception occurred while executing 'SELECT a0_.brand AS brand_0 FROM article a0_ WHERE a0_.brand IN (?, ?) GROUP BY a0_.brand' with params ["caporal", "adidas"]:
SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
Here is my repository ArticleRepository.php :
public function getBrandsByFilter($brands)
{
$qb = $this->createQueryBuilder('a');
$qb
->select('a')
->andWhere('a.brand IN (:brandFilter)')
->setParameter('brandFilter', $brands, Connection::PARAM_STR_ARRAY);
return $qb->getQuery()->getResult();
}
UPDATE : THIS ISSUE IS RESOLVED, IT CAME OF THE WRONG FORMAT OF THE ARRAY AS SAID IN THE COMMENTS. BUT ON THE OTHER SIDE I HAVE A NEW FOLLOWING PROBLEM.
In my controller I retrieve well the result of my query getBrandsByFilter() but I don't get to send it in a jsonResponse()toward Ajax.
Here is my controller code :
/**
* #Route("/ajax/request", options={"expose"=true}, name="ajax_request")
* #Method({"POST"})
*/
public function ajaxRequestAction(Request $request)
{
if ($request->isMethod('post')) {
$brands = $request->request->get('brand');
$repository = $this->getDoctrine()->getRepository('ArticleBundle:Article');
/* I retrieve my query result */
$articles = $repository->getBrandsByFilter($brands);
/* And send it toward Ajax */
$response = new JsonResponse();
return $response->setData(array('data' => $articles));
}
}
And here my ajax function :
$('#submitFilter').click(function () {
$.ajax({
type: 'POST',
url: Routing.generate("ajax_request"),
data: { brand: selectedBrand },
dataType: 'json'
})
// HERE I WANT RETRIEVE MY JsonRESPONSE
.done(function( data ) {
console.log(data);
for ( var i = 0; i < data.length; i++ ) {
Object.keys(data[i]).forEach(function (key) {
var propertyData = data[i][key];
//console.log(key);
//
})
}
});
})
When I debug the $articles variable in my controller, I have an array of objects like this :
array:8 [▼
0 => Article {#612 ▼
-id: 203
-fosUserId: null
-name: "article 1"
-category: "sous-vêtements"
-brand: "caporal"
-model: "running"
-gender: "unisex"
1 => Article {#610 ▶}
2 => Article {#631 ▶}
3 => Article {#619 ▶}
4 => Article {#657 ▶}
5 => Article {#635 ▶}
6 => Article {#695 ▶}
7 => Article {#633 ▶}
]
But when I debug data in my ajax I have an array of empty objects :
data: Array(8)
0: {}
1: {}
2: {}
3: {}
4: {}
5: {}
6: {}
7: {}
I don't know why I retrieve an array of EMPTY objects while the one that I send in the JsonRESPONSE is filled. Thank you for helping me understand.
$brands array the content should be in this way;
$brands = [
["caporal" => "caporal"], ["adidas" => "adidas"]
];
Or;
$brands = [
["caporal"], ["adidas"]
];
It will work but i think you should not use ->andWhere, ->where working this case.
I find the solution in an other issue wich unfortunately I have not seen before.
You have to replace getResult by getArrayResult to get an array well formatted of the query result. See the solution of the issue
public function getBrandsByFilter($brands)
{
$qb = $this->createQueryBuilder('a');
$qb
->select('a')
->andWhere('a.brand IN (:brandFilter)')
->setParameter('brandFilter', $brands, Connection::PARAM_STR_ARRAY);
/* Here replace getResult() by getArrayResult() */
return $qb->getQuery()->getArrayResult();
}
And in teh controller :
/**
* #Route("/ajax/request", options={"expose"=true}, name="ajax_request")
* #Method({"POST"})
*/
public function ajaxRequestAction(Request $request)
{
if ($request->isMethod('post')) {
$brands = $request->request->get('brand');
$repository = $this->getDoctrine()->getRepository('ArticleBundle:Article');
$articles = $repository->getBrandsByFilter($brands);
return new JsonResponse($articles);
}
}
Related
I have two models TeamMember and ProjectRequest.
A TeamMember can have one ProjectRequest, that is why I created the following Eloquent relationship on TeamMember:
class TeamMember extends Model {
//
protected $table = 'team_members';
protected $fillable = ['project_request_id'];
// Relations
public function projectTeam() {
return $this->hasOne('\App\Models\ProjectRequest', 'project_request_id');
}
}
In my Controller I want to query both tables, however it returns the failure message.
What is important to know is that $request->projectTeam is an array of emails, looking like this:
array:2 [
0 => "mv#something.com"
1 => "as#something.com"
]
Meaning that I need to bulk insert into team_members table the project_request_ id for each team member where the emails are in the array.
How can I do that in the right way? The following is my attempt:
public function createProjectTeam(Request $request){
try {
$title = $request->projectTitle;
$TeamMember = $request->projectTeam;
$projectRequest = ProjectRequest::create(['project_title' => $title]);
$projectRequestId = $projectRequest->id;
$projectTeam = $this->teamMembers->projectTeam()->create(['project_request_id'=> $projectRequestId])->where('email', $TeamMember);
//$projectTeam = TeamMember::createMany(['project_request_id' => $projectRequestId])->where($TeamMember);
//dd($projectTeam);
return $projectRequest.$projectTeam;
} catch(\Exception $e){
return ['success' => false, 'message' => 'project team creation failed'];
}
}
There are a few things you can do.
Eloquent offers a whereIn() method which allows you to query where a field equals one or more in a specified array.
Secondly, you can use the update() method to update all qualifying team members with the project_request_id:
public function createProjectTeam(Request $request)
{
try {
$projectRequest = ProjectRequest::create(['project_title' => $request->projectTitle]);
TeamMember::whereIn('email', $request->projectTeam)
->update([
'project_request_id' => $projectRequest->id
]);
return [
'success' => true,
'team_members' => $request->projectTeam
];
} catch(\Exception $e) {
return [
'success' => false,
'message' => 'project team creation failed'
];
}
}
I hope this helps.
I need to update the database table according to the edited data.
controller
public function update(Request $request)
{
$subscriptionplan = SubscriptionPlan::find($request->id);
$subscriptionplan->update($request->all());
return back();
}
But nothing happens when I submit the form. When I use dd($request->all()); at the beginning of the function, it correctly shows the edited data as follows.
array:10 [▼
"_method" => "patch"
"_token" => "gOCL4dK6TfIgs75wV87RdHpFZkD7rBpaJBxJbLHF"
"editname" => "SUP_EVA_001"
"editdesc" => "des"
"editprice" => "1000.050"
"editlimit" => "1"
"editperunit" => "20.000"
"editexceedunit" => "30.000"
"productid" => "1"
"id" => "1"
]
But database has not been updated.
My table name is Table: subscription_plans and model is SubscriptionPlan
These are the table columns:
protected $fillable = [
'name',
'description',
'price',
'usage_limit',
'charge_per_unit',
'charge_per_unit_exceed',
'is_limit_exceed_considered',
'product_id'
];
Any idea on how to solve it or what I have done wrong?
If your solution did not work, try the 1by1 like this.
public function update(Request $request)
{
$subscriptionplan = SubscriptionPlan::find($request->id);
$subscriptionplan->_method = $request->_method;
$subscriptionplan->_token = $request->_token;
$subscriptionplan->editname = $request->editname;
$subscriptionplan->editdesc = $request->editdesc;
$subscriptionplan->editprice = $request->editprice;
$subscriptionplan->editlimit = $request->editlimit;
$subscriptionplan->editperunit = $request->editperunit;
$subscriptionplan->editexceedunit = $request->editexceedunit;
$subscriptionplan->productid = $request->productid;
$subscriptionplan->save();
return back();
}
In order for Laravel to automatically fill the model attributes, the indexes of the array passed to the fill method must correspond to your model attributes names.
Also, instead of
$subscriptionplan->update($request->all());
Use
$subscriptionplan->fill($request->all());
Then save the subscription plan with $subscriptionplan->save();
I use audit-stash plugin which works fine with all my tables. But I have a particular function in which the user selects rows with checkboxes, and then changes a specific field to all of them. The table audits contains a fields called "primary_key" which seems not working for such case.
in my Controller, function, I put this:
$this->request->data;
$data = $this->request->data;
if($this->request->is(['patch', 'post', 'put']))
{
$ids = $this->request->data('data.AssetsAssignations.id');
$room_id = $this->request->data('room_id');
$this->AssetsAssignations->updateAll(
['room_id ' => $room_id ],
['id IN' => $ids]
);
}
in my table, I used this:
$this->addBehavior('AuditStash.AuditLog');
I was told that there is no way around this for audit-stash, because updateAll bypasses model callbacks by directly sending a query to the database.
I was suggested to update records one by one if I need to keep the log.
How can I transform my updateAll() code into a Save() loop ?
This try did not work for me, using save() and saveMany() :
$this->request->data;
$data = $this->request->data;
if($this->request->is(['patch', 'post', 'put']))
{
$ids = $this->request->data('data.AssetsAssignations.id');
$asset_status_id = $this->request->data('asset_status_id');
foreach($ids as $id) {
$this->AssetsAssignations->saveMany(
['asset_status_id ' => $asset_status_id ]
);
}
}
thanks in advance.
Actually you don't have to call get($id) for every id. This get the entity from the table and causes a lot of useless queries
if($this->request->is(['patch', 'post', 'put']))
{
$ids = $this->request->data('data.AssetsAssignations.id');
$asset_status_id = $this->request->data('asset_status_id');
$assetsAssignationsTable = TableRegistry::get('AssetsAssignations');
foreach($ids as $id) {
$assetsAssignation = $assetsAssignationsTable->newEntity(); // returns an empty entity
$assetsAssignation->id = $id; // assign the id to the entity
$assetsAssignation->asset_status_id = $asset_status_id;
$assetsAssignationsTable->save($assetsAssignation);
}
}
Thanks to Greg, this code worked for me:
use Cake\ORM\TableRegistry;
...
if($this->request->is(['patch', 'post', 'put']))
{
$ids = $this->request->data('data.AssetsAssignations.id');
$asset_status_id = $this->request->data('asset_status_id');
$assetsAssignationsTable = TableRegistry::get('AssetsAssignations');
foreach($ids as $id) {
$assetsAssignation = $assetsAssignationsTable->get($id); // Return assetsAssignation with id
$assetsAssignation->asset_status_id = $asset_status_id;
$assetsAssignationsTable->save($assetsAssignation);
}
}
I have a code:
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('name')
[..]
This is a property from translation (KNP translatable). I tried use:
translations.name - label is sortable, but values are missing
name or translate.name - label is not sortable, but values are ok
I don't have any idea how I should to do this. Maybe someone here can help me?
Did you try $listMapper->add('name',null, array('sortable'=>true)) ?
Ok, I made it.
1) Create abstract admin class:
use Sonata\AdminBundle\Admin\AbstractAdmin as BaseAbstractAdmin;
abstract class AbstractAdmin extends BaseAbstractAdmin { .. }
2) Use this class in your admin classes:
class UserAdmin extends AbstractAdmin { .. }
3) Add this to your column definition:
->add(
'fieldName',
null,
[
'sortable' => true,
'sort_field_mapping' => ['fieldName' => 'id'],
'sort_parent_association_mappings' => [],
]
)
4) Add this method to your abstract admin class:
protected function prepareQueryForTranslatableColumns($query)
{
$currentAlias = $query->getRootAliases()[0];
$locale = $this->request->getLocale();
$parameters = $this->getFilterParameters();
$sortBy = $parameters['_sort_by'];
$fieldDescription = $this->getListFieldDescription($sortBy);
$mapping = $fieldDescription->getAssociationMapping();
$entityClass = $mapping['targetEntity'] ?: $this->getClass();
if ($mapping) {
$mappings = $fieldDescription->getParentAssociationMappings();
$mappings[] = $mapping;
foreach ($mappings as $parentMapping) {
$fieldName = $parentMapping['fieldName'];
$query->leftJoin($currentAlias . '.' . $fieldName, $fieldName);
$currentAlias = $fieldName;
}
}
$query
->leftJoin(
$currentAlias . '.translations',
'tr',
'with',
'tr.locale = :lang OR
(NOT EXISTS(SELECT t.id FROM ' . $entityClass . 'Translation t WHERE t.translatable = tr.translatable AND t.locale = :lang)
AND tr.locale = :lang_default)'
)
->addOrderBy('tr.name', $parameters['_sort_order'])
->setParameter(':lang', $locale)
->setParameter(':lang_default', 'en');
return $query;
}
I use JOIN to get translations for currently selected locale and, if translation doesn't exist yet for current locale, I add translation for default locale (it is a reason for use NOT EXIST).
5) Add this method to your admin class:
public function createQuery($context = 'list')
{
$query = parent::createQuery($context);
if ('list' === $context) {
$parameters = $this->getFilterParameters();
$sortBy = $parameters['_sort_by'];
if (in_array($sortBy, ['fieldName', 'fieldName.fieldName2', 'fieldName3', ..])) {
$query = parent::prepareQueryForTranslatableColumns($query);
}
}
return $query;
}
Late answer but I was having the same problem.
The easiest solution for me was to set the right property mapping like this:
$listMapper->add(
'translations',
null,
[
'sortable' => true,
'associated_property' => 'name',
'sort_field_mapping' => [
'fieldName' => 'name',
],
'sort_parent_association_mappings' => [
['fieldName' => 'translations'],
],
]
);
I am a newbie in Laravel, so everything is under exploration period. I use angular http post to send data over to laravel and in laravel controller i am able to
dd($request)
Request {#40
#json: ParameterBag {#32
#parameters: array:4 [
"GPTour_id" => 1
"customer_id" => 1
"status" => "Confirmed"
"note" => "asdfasdf"
]
}
#userResolver: Closure {#300
class: "Illuminate\Auth\AuthServiceProvider"
this: AuthServiceProvider {#22 …}
use: array:1 [
"$app" => Application {#3
#basePath: "/Users/haophung/Dropbox/server/websites/nglaravelyep/laravel-backend"
#hasBeenBootstrapped: true
#booted: true
#bootingCallbacks: []
However, if i use
$request->input('key')
i got $request is undefined. Please advise!!!
public function addGospelCustomer(Request $request)
{
if ($request) {
$customer_id = $request->get('customer_id');
$tour_id = $request->get('GPTour_id');
$validator = Validator::make($request->all(), [
'customer_id' =>'required'
]);
if ($validator->fails()) {
return response()->json(['error' => $validator->errors()], 406);
}
$gospel_customer = Gospel_tour::find($tour_id)->with(['customers' => function($query) {
$query->where('id', $customer_id);
}])->first();
if ($gospel_customer === 'null') {
return response()->json(['error' => "The Customer is already on the list"], 406);
}
return 'success';//response()->json(['success' => $request], 200);
}else {
return response()->json(['error' =>'can not add customer'], 401);
}
}
ErrorException in GospelController.php line 60:
Undefined variable: customer_id
I think the problem is
$gospel_customer = Gospel_tour::find($tour_id)->with(['customers' => function($query) {
$query->where('id', $customer_id);
}])->first();
I can echo $customer_id out, but in this eloquent is not defined
You need to typehint requestion in your function definition
public function name(Request $request) {}
And use it like
$key = $request->key;
$key = $request->get('key');
Or use the global function
$key = request('key');
Update
Where you have the error exception do
$gospel_customer = Gospel_tour::find($tour_id)->with(['customers' => function($query) use ($customer_id) {
$query->where('id', $customer_id);
}]);
The error occurs because you are inside a closure, and it doesn't have access to external variables.