Laravel 4: Why can't I use aliases in my laravel code - laravel-4

Here's my code:
public function getReports()
{
$reports=DB::table('reports')
->select(array('*',DB::raw('reports.id','reports.departmentID','reports.officerID','reports.created_at','reports.report','reports.title','department.name','posts.name AS pname')))
->leftjoin('department','reports.departmentID','=','department.id')
->leftjoin('posts','reports.postID','=','posts.id')
->leftjoin('users','reports.officerID','=','users.id')
->leftjoin('events','events.id','=','reports.eventID')
->orderBy('reports.id','DESC')
->get();
$reportsArray=array();
foreach($reports as $row)
{
$reportsArray[]=array(
'id'=>$row->id,
'report'=>$row->report,
'title'=>$row->title,
'departmentName'=>$row->name,
'created_at'=>$row->created_at,
'post'=>$row->pname,
);
}
return View::make('reports.reports')
->with('reports',$reportsArray);
}
I'm getting the following error when I load the view: Undefined property: stdClass::$pname
This is basically a problem because i need to use aliases in many instances. And the error is basically the same when I try to use a column alias with any column. Can anyone see where the problem is with my code?
My Model:
class Report extends Eloquent
{
protected $table = 'reports';
protected $fillable= array(
'title','reportDate',,'departmentID','date','eventID','officerID','postID‌​',
);
}

Related

Unsupported operand types: array + App\StockOut Laravel

I wanna ask why I my query isn't work when I try in another case, I have query like this :
$getData = StockOut::select("*",
StockOut::raw('group_concat(stock_outs.id_stock_out) as id_stock_outs'),
)
->with(['stock_ins' => function ($query) {
$query->select('id_stock_in', 'stock_in_id_type')
->with(['type_of_items' => function ($query) {
$query->select('id_type_item', 'type_id_item', 'code_type_of_item', 'type_of_item');
}]);
}])
->groupBy('stock_outs.stock_out_id_stock_in')
->get()
->groupBy('stock_ins.stock_in_id_type')->map(function ($group) {
return [
'id_stock_ins' => $group->pluck('stock_ins.id_stock_in')->join(','),
'id_stock_outs' => $group->pluck('id_stock_outs')->join(',')
] + $group->first();
})->values();
I have error like this :
message: "Unsupported operand types: array + App\StockOut"
In StockOut model :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class StockOut extends Model
{
protected $primaryKey = "id_stock_out";
protected $fillable = [
'stock_out_id_location', 'stock_out_id_stock_in', 'date_of_stock_out', 'quantity', 'description', 'created_by', 'edited_by'
];
public function locations()
{
return $this->belongsTo('App\Location', 'stock_out_id_location');
}
public function stock_ins()
{
return $this->belongsTo('App\StockIn', 'stock_out_id_stock_in');
}
}
I really don't understand about my error now, because when I try my query in another project is working and nothing error happened, I hope someone can help me to guide me solve my problem, Thank you before.
Check value on $group. It must be of type array in order for + operator to work.
Currently you might be doing
[/* ... */] + <an eloquent model>
which will give you that error

laravel 5.7 with() method

i'm trying to query two related model in the controller but the request failed.
here is my code:
$product = 'smartphone';
$prod = Produit::where('designation', $product)->with('tarifs')->get();
foreach($prod->tarifs as $tarif){
$tarif->prixAchat = $prix[$id];
$tarif->save();
}
this is the error message: Property [tarifs] does not exist on this collection instance.
i have this in the Produit model:
public function tarifs()
{
return $this->hasMany('App\Models\Tarif');
}
and the Tarif model:
public function produit()
{
return $this->belongsTo('App\Models\Produit');
}
you're getting a collection of products, and trying to get tarifs of it, thats why it throws the error, heres the solution
$product = 'smartphone';
$products = Produit::where('designation', $product)->get();
foreach($products as $prod){
foreach($prod->tarifs as $tarif){
$tarif->prixAchat = $prix[$id];
$tarif->save();
}
}

ErrorException (E_ERROR) :Trying to get property of non-object. when i trying implode array to string in index.blade.php

index.blade.php
#php
$p = [];
foreach($p->genres as $genre){
$genres[] = $genre->genres;
}
$genre = implode(",", $genres);
#endphp
<span>{{$genre}}</span>
Controller
public function index()
{
$series = Series::all();
return view('admin/series/index',['series' => $series]);
}
model Genres.php
class Genres extends Model
{
protected $primarykey= 'id';
protected $fillable = ['genres'];
public function series()
{
return $this->belongsToMany(Series::class);
}
}
Model Series.php
class Series extends Model
{
protected $table = 'series';
protected $primarykey='id';
protected $fillable = ['title','country','japanese','year','synonyms','trailer','image','network','rating','duration','genres','aired','directors','screenwriters','score','type','episode','synopsis'];
public function genres(){
return $this->belongsToMany(Genres::class);
}
}
I want to display data from different databases using multiple table relationships, but the data is still a compilation array to bring it up.
and compilation I asked a friend. I was told to use a code like the one in index.blade.php. and return like this
ErrorException (E_ERROR) Try to get properties that are not objects
You are accessing array with -> whereas only the object can be accessed with arrow. To access array keys you have to use $array['key'] approach.
Arrays and objects are two different data types, so to access their inner data, you've to use their respective approaches.
You are looping wrong variables/collections. You need to make some changes to make it work. Below code should solve your problem.
#php
$p = [];
foreach($series as $ser){
foreach($ser->genres as $genre){
$p[] = $genre->genres;
}
}
$gen = implode(",", $p);
#endphp
<span>{{$gen}}</span>
You are setting series from the controller so inside the view you must loop over the series first.
#foreach($series as $s){
// then your code should be take place.
#php
$genres = [];
foreach($s->genres as $genre){
$genres[] = $genre->genres;
}
$genre = implode(",", $genres);
#endphp
<span>{{$genre}}</span>
#endforeach

Laravel API APP Many-Many Relationship, how to return specific information in JSON?

I been trying to figure this out for some time now. Basically i got 2 models ' Recipe ', ' Ingredient ' and one Controller ' RecipeController ' .
I'm using Postman to test my API. When i go to my get route which uses RecipeController#getRecipe, the return value is as per the pic below:
Return for Get Route
If i want the return value of the get route to be in the FORMAT of the below pic, how do i achieve this? By this i mean i don't want to see for the recipes: the created_at column, updated_at column and for ingredients: the pivot information column, only want name and amount column information.
Return Value Format I Want
Recipe model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Recipe extends Model
{
protected $fillable = ['name', 'description'];
public function ingredients()
{
return $this->belongsToMany(Ingredient::class,
'ingredient_recipes')->select(array('name', 'amount'));
}
}
Ingredient Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Ingredient extends Model
{
protected $fillable = ['name', 'amount'];
}
RecipeController
<?php
namespace App\Http\Controllers;
use App\Ingredient;
use App\Recipe;
use Illuminate\Http\Request;
class RecipeController extends Controller {
public function postRecipe(Request $request)
{
$recipe = new Recipe();
$recipe->name = $request->input('name');
$recipe->description = $request->input('description');
$recipe->save();
$array_ingredients = $request->input('ingredients');
foreach ($array_ingredients as $array_ingredient) {
$ingredient = new Ingredient();
$ingredient->name = $array_ingredient['ingredient_name'];
$ingredient->amount = $array_ingredient['ingredient_amount'];
$ingredient->save();
$recipe->ingredients()->attach($ingredient->id);
}
return response()->json(['recipe' => $recipe . $ingredient], 201);
}
public function getRecipe()
{
$recipes = Recipe::all();
foreach ($recipes as $recipe) {
$recipe = $recipe->ingredients;
}
$response = [
'recipes' => $recipes
];
return response()->json($response, 200);
}
API Routes:
Route::post('/recipe', 'RecipeController#postRecipe')->name('get_recipe');
Route::get('/recipe', 'RecipeController#getRecipe')->name('post_recipe');
Thanks Guys!
I think your best solution is using Transformer. Using your current implementation what I would recommend is fetching only the needed field in your loop, i.e:
foreach ($recipes as $recipe) {
$recipe = $recipe->ingredients->only(['ingredient_name', 'ingredient_amount']);
}
While the above might work, yet there is an issue with your current implementation because there will be tons of iteration/loop polling the database, I would recommend eager loading the relation instead.
But for the sake of this question, you only need Transformer.
Install transformer using composer composer require league/fractal Then you can create a directory called Transformers under the app directory.
Then create a class called RecipesTransformer, and initialize with:
namespace App\Transformers;
use App\Recipe;
use League\Fractal\TransformerAbstract;
class RecipesTransformer extends TransformerAbstract
{
public function transform(Recipe $recipe)
{
return [
'name' => $recipe->name,
'description' => $recipe->description,
'ingredients' =>
$recipe->ingredients->get(['ingredient_name', 'ingredient_amount'])->toArray()
];
}
}
Then you can use this transformer in your controller method like this:
use App\Transformers\RecipesTransformer;
......
public function getRecipe()
{
return $this->collection(Recipe::all(), new RecipesTransformer);
//or if you need to get one
return $this->item(Recipe::first(), new RecipesTransformer);
}
You can refer to a good tutorial like this for more inspiration, or simply go to Fractal's page for details.
Update
In order to get Fractal collection working since the example I gave would work if you have Dingo API in your project, you can manually create it this way:
public function getRecipe()
{
$fractal = app()->make('League\Fractal\Manager');
$resource = new \League\Fractal\Resource\Collection(Recipe::all(), new RecipesTransformer);
return response()->json(
$fractal->createData($resource)->toArray());
}
In case you want to make an Item instead of collection, then you can have new \League\Fractal\Resource\Item instead. I would recommend you either have Dingo API installed or you can follow this simple tutorial in order to have in more handled neatly without unnecessary repeatition

Calling same eloquent statement in several controllers

I have an eloquent statement like this:
$constraint = function ($query) {
$query->where('session', Session::getId());
};
$selectedImages = ImageSession::with(['folder' => $constraint])
->whereHas('folder', $constraint)
->where('type', 'single')
->get();
Which I need to call in several controllers.
How is the best way to do it without putting this code every time?
Should I put this code in the Model? but how I put the ImageSession::with if it is inside the same model that has ImageSession class?
In the controller do I have to write...
$imageSession_table = new ImageSession;
$selectedImages = $imageSession_table->getSelectedImages();
Well there are several solutions to this, but one rule that I have learned is whenever you are doing copy paste in the same file it means you need to create a function to encapsulate that code.
The same applies when you are copying and pasting the same code over classes/controllers it means you need to create a class that will have a method, that will encapsulate that code.
Now you could in fact change your model and this depends on your application and what kind of level of abstraction you have.
Some people tend to leave the models as pure as possible and then use transformers, repositories, classes whatever you want to call it. So the flow of communication is something like this:
Models -> (transformers, repositories, classes) -> Controllers or other classes
If that's the case just create a ImageSessionRepository and in there have your method to get the selected images:
<?php namespace Your\Namespace;
use ImageSession;
use Session;
class ImageSessionRepository
{
protected $imageSession;
public function __construct(ImageSession $imageSession)
{
$this->imageSession = $imageSession;
}
public function getSelectedImages($sessionId = false){
if(!$sessionId){
$sessionId = Session::getId()
}
$constraint = function ($query) use ($sessionId){
$query->where('session', $sessionId);
};
$selectedImages = ImageSession::with(['folder' => $constraint])
->whereHas('folder', $constraint)
->where('type', 'single')
->get();
return $selectedImages;
}
}
Then on your controller you just inject it:
<?php namespace APP\Http\Controllers;
use Your\Namespace\ImageSessionRepository;
class YourController extends Controller
{
/**
* #var ImageSessionRepository
*/
protected $imageSessionRepository;
public function __construct(ImageSessionRepository $imageSessionRepository)
{
$this->imageSessionRepository = $imageSessionRepository;
}
public function getImages()
{
$selectedImages = $this->imageSessionRepository->getSelectedImages();
//or if you want to pass a Session id
$selectedImages = $this->imageSessionRepository->getSelectedImages($sessionID = 1234);
//return the selected images as json
return response()->json($selectedImages);
}
}
Another option is adding that code directly into your Model, using scopes, more info here
So on your ImageSession Model just add this function:
public function scopeSessionFolder($query, $session)
{
$constraint = function ($constraintQuery) use ($sessionId){
$query->where('session', $sessionId);
};
return $query->with(['folder' => $constraint])
->whereHas('folder', $constraint);
}
And on your controller just do this:
$selectedImages = ImageSession::sessionFolder(Session::getId())
->where('type', 'single')
->get();
Or you can include everything in your scope if that's your case
public function scopeSessionFolder($query, $session)
{
$constraint = function ($constraintQuery) use ($sessionId){
$query->where('session', $sessionId);
};
return $query->with(['folder' => $constraint])
->whereHas('folder', $constraint);
->where('type', 'single');
}
And then again on your controller you will have something like this:
$selectedImages = ImageSession::sessionFolder(Session::getId())
->get();
Just a side note I haven't tested this code, so if you just copy and paste it it's possible that you find some errors.

Resources