Doctrine: use foreach in a find one - php

I want to use 99% of my code to do two queries.
When accessing api.com/jobs it will display all my jobs, but acessing api.com/jobs/65 will only display that entire job.
My improvement is to have an if before the foreach, to detect whether it is one single id or to list all.
My code looks like this:
$Repo = $entityManager->getRepository('App\Models\Entity\Jobs');
if ($param){
$jobs = $Repo->find($param);
} else{
$jobs = $Repo->findAll();
}
foreach ($jobs as $j_key=>$job){
...
}
The problem is: the findAll() is doing great but I can't enter the foreach with the find() only;
Is any way to do what I want?

If you must use this approach (I would prefer to separate concerns) put the result into an array;
edited
$Repo = $entityManager->getRepository('App\Models\Entity\Jobs');
if ($param){
$jobs[] = $Repo->find($param);
} else{
$jobs = $Repo->findAll();
}
foreach ($jobs as $j_key => $job){
// there is a risk that whats in $jobs might not be what you expect. So check.
if(!$job instanceOf Jobs::class) {
continue;
}
}
alternatively, use findBy as itll return a Collection object which will iterate.
$Repo->findBy(['column' => 'value']);

I would suggest having different pieces of code to deal with the two cases but, if you would rather keep them together:
$Repo = $entityManager->getRepository('App\Models\Entity\Jobs');
if ($param){
$jobs = array($Repo->find($param));
} else{
$jobs = $Repo->findAll();
}
foreach ($jobs as $j_key=>$job){
...
}
This will create an array with a single element in the case a request is made for a single job, and a request for multiple jobs will return all the matching jobs.

Related

Work with foreach in Laravel: delete same values

I found way to delete duplicate values in the result but it doesn't work correctly. How to fix it?
I have next code:
public function getListPositionByApplication($app_id){
// $app_id = \Request::input('app_id');
$list = SparePartApplicationPositionProvider::where('app_id',$app_id)->with(['provider','application_position'])->orderBy('apos_id')
->get();
$aa=0;
foreach ($list as $value) {
if($value->apos_id==$aa){
$value->application_position->name_detail='----';
}
$aa = $value->apos_id;
Log::info($value->apos_id);
}
return $list;
}
Log::info give next information: 26,26,26,26,26,26,27,27,27,27,27,27,28
but $value->application_position->name_detail have '----' in all cases with the exception of last value
#Hussein is right, group by the common column and don't do a foreach. Let the Eloquent DB do the heavy lifting. Notice the callback where you include your second table.
$list = SparePartApplicationPositionProvider::where('app_id',$app_id)
->with(['provider','application_position' => function ($query){
$query->groupBy('name_detail');
}])
->orderBy('apos_id')
->get();
You can try collection unique() method.
https://laravel.com/docs/master/collections#method-unique

Laravel 5.5 Collection where like

i am filtering data using collections. But i need to use like method. I had tried to write like this : ('name', 'LIKE', '%value%') but it did not work.
Here is my method :
protected function filterData(Collection $collection, $transformer) {
foreach (request()->query() as $query => $value) {
$attribute = $transformer::originalAttribute($query);
if (isset($attribute, $value)) {
$collection = $collection->where($attribute, $value);
}
}
return $collection;
}
The 1st question is whether you really know what you are doing. If you take data from database and then filter it just to take some elements it's definitely not the best way because you can take from database for example 100000 records just to finally have only 2 elements and it will kill your application performance.
But assuming you really want to filter using Support collection, there is no where together with LIKE because you are just filtering an array. If you want to use something similar to like instead of:
$collection = $collection->where('name', $value);
you can use:
$collection = $collection->reject(function($element) use ($value) {
return mb_strpos($element->name, $value) === false;
});
depending on what you really have in collection instead of $element->name you might need to use $element['name']

How to delete multiple row from DB table by laravel?

I want to delete all comments from comments table.I did that by doing this but this is not the laravel way. Anyone answer the correct steps please .
$comments = Comment::where('post_id',$id)->get();
if(count($comments)>1)
{
$comment_id= [];
foreach ($comments as $i)
{
$comment_id[] = $i->id;
}
for($i=0;$i<count($comments);$i++)
{
Comment::find($comment_id[$i])->delete();
}
}
elseif (count($comments)==1)
{
$comments->delete();
}
Since each Eloquent model serves as a query builder, try this, all in one line:
Comment::where('post_id',$id)->delete();
Tested in tinker, works as expected, returns count of deleted rows.
Documentation: https://laravel.com/docs/5.3/queries#deletes
You can try the following approach:
public function deleteAll(Request $request)
{
$ids = $request->ids;
Comment::whereIn('id',explode(",",$ids))->delete();
}
DB::table('users')->whereIn('id', $ids_to_delete)->delete();
or
$org-products()->whereIn('id', $ids)->delete();
Collect only ids from your command like below and destroy by model.
$yourRaws = YourModel::where('name', 'Enver')->get();
...
YourModel::destroy($yourRaws->pluck('id')->toArray());
Enjoy Your Coding !

Efficient way to segregate data in php

I am using Laravel and I want to retrieve the data using Eloquent.
My controller:
public function getquesdet(){
$id = Request::input('id');
$question = Question::where('q_id','=',$id)->with('qtags.tags')->with('comments')->with('answers')
->first();
$i=0;
$tagnames[]=0;
foreach ($question['qtags'] as $value) {
$tagnames[$i] = $value['tags']['tag'];
$i++;
}
$j=0;
$comments[]=0;
foreach ($question['comments'] as $value) {
$comments[$j] = $value['comment'];
$j++;
}
$k=0;
$answers[]=0;
foreach ($question['answers'] as $value) {
$answers[$k] = $value['answer'];
$k++;
}
return array('question'=>$question['title'],'body'=>$question['body'],'tags'=>$tagnames,'comments'=>$comments,'answer'=>$answers);
}
As you can see, I feel that the usage of foreach loops is not efficient. Using for loops might take more time. All I want is to know that if there is any efficient workaround to this.
The $question is returned as :
I think that looks like an efficient solution. Three for loops after each other gives complexity O(3n) -> O(n) which is good and should be fast. If you have very large collections of comments, tagnames and questions I would try to solve the problem at SQL level which should be even faster, but for small resultsets this should be good enough.
Big O notation
If you want selected columns from the table then you can use select() method as:
$question = Question::where('q_id','=',$id)
->select('title', 'body')
->with([
'qtags' => function($q) {
$q->select('tag');
},
'qtags.tags' => function($q) {
$q->select('comment');
},
'answers' => function($q) {
$q->select('answer');
}
])
->first();
Then you can return it as an array:
return $question->toArray();
Docs

Best practice to delete array of objects in Doctrine

i have a question. I'm trying to delete array of objects and thinking that the approach i'm trying to implement could be optimized more.
Does this function sends only one query to database to delete all of the objects ?
public function removeData(array $files)
{
foreach ($files as $file) {
$this->entityManager->remove($file);
}
$this->entityManager->flush();
return true;
}
Maybe i should use bulk deletion ?
I need some opinions.
Thanks.
You can do it with query builder like this :
$qb = $em->createQueryBuilder();
$qb->delete('Foods', 'f');
$qb->where("f.name = {$pizza}");

Categories