User Transformer::$availableIncludes must be array - arrays

I am using Laravel 6.20 version with php version 8 get this error when call the user transfomer
here is my code
model class
<?php
namespace App\Models;
use Carbon\Carbon;
use App\Models\Country;
use App\Models\Access\Role;
use App\Models\Admin\Staff;
use App\Models\Admin\Driver;
use App\Models\Admin\Owner;
use App\Models\Request\Request;
use App\Models\Master\Developer;
use App\Models\Master\PocClient;
use App\Models\Traits\HasActive;
use App\Models\Admin\AdminDetail;
use App\Models\Admin\UserDetails;
use App\Models\Payment\UserWallet;
use Laravel\Passport\HasApiTokens;
use App\Models\LinkedSocialAccount;
use App\Models\Payment\DriverWallet;
use App\Base\Services\OTP\CanSendOTP;
use App\Models\Traits\DeleteOldFiles;
use App\Models\Traits\UserAccessTrait;
use Illuminate\Support\Facades\Storage;
use Illuminate\Notifications\Notifiable;
use App\Models\Payment\UserWalletHistory;
use App\Models\Traits\HasActiveCompanyKey;
use App\Models\Traits\UserAccessScopeTrait;
use App\Base\Services\OTP\CanSendOTPContract;
use Nicolaslopezj\Searchable\SearchableTrait;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Models\Request\FavouriteLocation;
class User extends Authenticatable implements CanSendOTPContract
{
use CanSendOTP,
DeleteOldFiles,
HasActive,
HasApiTokens,
Notifiable,
UserAccessScopeTrait,
UserAccessTrait,
SearchableTrait,
HasActiveCompanyKey;
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'username', 'email', 'password', 'mobile', 'country', 'profile_picture', 'email_confirmed', 'mobile_confirmed', 'email_confirmation_token', 'active','fcm_token','login_by','apn_token','timezone','rating','rating_total','no_of_ratings','refferal_code','referred_by','social_nickname','social_id','social_token','social_token_secret','social_refresh_token','social_expires_in','social_avatar','social_avatar_original','social_provider','company_key','lang'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token', 'email_confirmation_token',
];
/**
* The attributes that have files that should be auto deleted on updating or deleting.
*
* #var array
*/
public $deletableFiles = [
'profile_picture',
];
/**
* The attributes that can be used for sorting with query string filtering.
*
* #var array
*/
public $sortable = [
'id', 'name', 'username', 'email', 'mobile', 'profile_picture', 'last_login_at', 'created_at', 'updated_at',
];
/**
* The relationships that can be loaded with query string filtering includes.
*
* #var array
*/
public $includes = [
'roles', 'otp','requestDetail'
];
/**
* The accessors to append to the model's array form.
*
* #var array
*/
protected $appends = [
];
/**
* Get the Profile image full file path.
*
* #param string $value
* #return string
*/
// public function getProfilePictureAttribute($value)
// {
// if (empty($value)) {
// $default_image_path = config('base.default.user.profile_picture');
// return env('APP_URL').$default_image_path;
// }
// return Storage::disk(env('FILESYSTEM_DRIVER'))->url(file_path($this->uploadPath(), $value));
// }
public function getProfilePictureAttribute($value)
{
if (!$value) {
$default_image_path = config('base.default.user.profile_picture');
return env('APP_URL').$default_image_path;
}
return Storage::disk(env('FILESYSTEM_DRIVER'))->url(file_path($this->uploadPath(), $value));
}
/**
* Override the "boot" method of the model.
*
* #return void
*/
public static function boot()
{
parent::boot();
// Model event handlers
}
/**
* Set the password using bcrypt hash if stored as plaintext.
*
* #param string $value
*/
public function setPasswordAttribute($value)
{
$this->attributes['password'] = (password_get_info($value)['algo'] === 0) ? bcrypt($value) : $value;
}
/**
* The roles associated with the user.
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function roles()
{
return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id');
}
/**
* The OTP associated with the user's mobile number.
*
* #return \Illuminate\Database\Eloquent\Relations\hasOne
*/
public function otp()
{
return $this->hasOne(MobileOtp::class, 'mobile', 'mobile');
}
/**
* Get the user model for the given username.
*
* #param string $username
* #return \Illuminate\Database\Eloquent\Model|null|static
*/
public function findForPassport($username)
{
return $this->where($this->usernameField($username), $username)->first();
}
/**
* Get the username attribute based on the input value.
* Result is either 'email' or 'mobile'.
*
* #param string $username
* #return string
*/
public function usernameField($username)
{
return is_valid_email($username) ? 'email' : 'mobile';
}
/**
* The default file upload path.
*
* #return string|null
*/
public function uploadPath()
{
return config('base.user.upload.profile-picture.path');
}
/**
* The Staff associated with the user's id.
*
* #return \Illuminate\Database\Eloquent\Relations\hasOne
*/
public function admin()
{
return $this->hasOne(AdminDetail::class, 'user_id', 'id');
}
/**
* The Staff associated with the user's id.
*
* #return \Illuminate\Database\Eloquent\Relations\hasOne
*/
public function developer()
{
return $this->hasOne(Developer::class, 'user_id', 'id');
}
/**
* The user wallet history associated with the user's id.
*
* #return \Illuminate\Database\Eloquent\Relations\hasOne
*/
public function userWalletHistory()
{
return $this->hasMany(UserWalletHistory::class, 'user_id', 'id');
}
/**
* The favouriteLocations associated with the user's id.
*
* #return \Illuminate\Database\Eloquent\Relations\hasOne
*/
public function favouriteLocations()
{
return $this->hasMany(FavouriteLocation::class, 'user_id', 'id');
}
public function userWallet()
{
return $this->hasOne(UserWallet::class, 'user_id', 'id');
}
public function driverWallet()
{
return $this->hasOne(DriverWallet::class, 'user_id', 'id');
}
/**
* The Driver associated with the user's id.
*
* #return \Illuminate\Database\Eloquent\Relations\hasOne
*/
public function driver()
{
return $this->hasOne(Driver::class, 'user_id', 'id');
}
public function accounts()
{
return $this->hasMany(LinkedSocialAccount::class, 'user_id', 'id');
}
public function requestDetail()
{
return $this->hasMany(Request::class, 'user_id', 'id');
}
/**
* The Driver associated with the user's id.
*
* #return \Illuminate\Database\Eloquent\Relations\hasOne
*/
public function userDetails()
{
return $this->hasOne(UserDetails::class, 'user_id', 'id');
}
/**
* Get formated and converted timezone of user's created at.
*
* #param string $value
* #return string
*/
public function getConvertedCreatedAtAttribute()
{
if ($this->created_at==null||!auth()->user()->exists()) {
return null;
}
$timezone = auth()->user()->timezone?:env('SYSTEM_DEFAULT_TIMEZONE');
return Carbon::parse($this->created_at)->setTimezone($timezone)->format('jS M h:i A');
}
/**
* Get formated and converted timezone of user's created at.
*
* #param string $value
* #return string
*/
public function getConvertedUpdatedAtAttribute()
{
if ($this->updated_at==null||!auth()->user()->exists()) {
return null;
}
$timezone = auth()->user()->timezone?:env('SYSTEM_DEFAULT_TIMEZONE');
return Carbon::parse($this->updated_at)->setTimezone($timezone)->format('jS M h:i A');
}
/**
* Specifies the user's FCM token
*
* #return string
*/
public function routeNotificationForFcm()
{
return $this->fcm_token;
}
public function routeNotificationForApn()
{
return $this->apn_token;
}
protected $searchable = [
'columns' => [
'users.name' => 20,
'users.email'=> 20
],
];
/**
* The user that the country belongs to.
* #tested
*
* #return \Illuminate\Database\Eloquent\Relations\belongsTo
*/
public function countryDetail()
{
return $this->belongsTo(Country::class, 'country', 'id');
}
public function owner()
{
return $this->hasOne(Owner::class, 'user_id', 'id');
}
}
controller class
class AccountController extends ApiController
{
/**
* Get the current logged in user.
* #group User-Management
* #return \Illuminate\Http\JsonResponse
* #responseFile responses/auth/authenticated_driver.json
* #responseFile responses/auth/authenticated_user.json
*/
public function me()
{
$user = User::where('id', auth()->user()->id)->companyKey()->first();
$user = fractal($user, new UserTransformer)->parseIncludes(['onTripRequest.driverDetail','onTripRequest.requestBill','metaRequest.driverDetail','favouriteLocations']);
}
return $this->respondOk($user);
}
transfomer class
class UserTransformer extends Transformer
{
/**
* Resources that can be included if requested.
*
* #var array
*/
protected $availableIncludes = [
'roles','onTripRequest','metaRequest','favouriteLocations'
];
/**
* Resources that can be included default.
*
* #var array
*/
protected $defaultIncludes = [
'sos'
];
/**
* A Fractal transformer.
*
* #return array
*/
public function transform(User $user)
{
$params = [
'id' => $user->id,
'name' => $user->name,
'username' => $user->username,
'email' => $user->email,
'mobile' => $user->mobile,
'profile_picture' => $user->profile_picture,
'active' => $user->active,
'email_confirmed' => $user->email_confirmed,
'mobile_confirmed' => $user->mobile_confirmed,
'last_known_ip' => $user->last_known_ip,
'last_login_at' => $user->last_login_at,
'rating' => round($user->rating, 2),
'no_of_ratings' => $user->no_of_ratings,
'refferal_code'=>$user->refferal_code,
'currency_code'=>$user->countryDetail->currency_code,
'currency_symbol'=>$user->countryDetail->currency_symbol,
'map_key'=>env('GOOGLE_MAP_KEY'),
'show_rental_ride'=>true,
// 'created_at' => $user->converted_created_at->toDateTimeString(),
// 'updated_at' => $user->converted_updated_at->toDateTimeString(),
];
$referral_comission = get_settings('referral_commision_for_user');
$referral_comission_string = 'Refer a friend and earn'.$user->countryDetail->currency_symbol.''.$referral_comission;
$params['referral_comission_string'] = $referral_comission_string;
return $params;
}
/**
* Include the roles of the user.
*
* #param User $user
* #return \League\Fractal\Resource\Collection|\League\Fractal\Resource\NullResource
*/
public function includeRoles(User $user)
{
$roles = $user->roles;
return $roles
? $this->collection($roles, new RoleTransformer)
: $this->null();
}
/**
* Include the request of the user.
*
* #param User $user
* #return \League\Fractal\Resource\Collection|\League\Fractal\Resource\NullResource
*/
public function includeOnTripRequest(User $user)
{
$request = $user->requestDetail()->where('is_cancelled', false)->where('user_rated', false)->where('driver_id', '!=', null)->first();
return $request
? $this->item($request, new TripRequestTransformer)
: $this->null();
}
/**
* Include the request meta of the user.
*
* #param User $user
* #return \League\Fractal\Resource\Collection|\League\Fractal\Resource\NullResource
*/
public function includeMetaRequest(User $user)
{
$request = $user->requestDetail()->where('is_completed', false)->where('is_cancelled', false)->where('user_rated', false)->where('driver_id', null)->where('is_later', 0)->first();
return $request
? $this->item($request, new TripRequestTransformer)
: $this->null();
}
/**
* Include the request meta of the user.
*
* #param User $user
* #return \League\Fractal\Resource\Collection|\League\Fractal\Resource\NullResource
*/
public function includeSos(User $user)
{
$request = Sos::select('id', 'name', 'number', 'user_type', 'created_by')
->where('created_by', auth()->user()->id)
->orWhere('user_type', 'admin')
->orderBy('created_at', 'Desc')
->companyKey()->get();
return $request
? $this->collection($request, new SosTransformer)
: $this->null();
}
/**
* Include the favourite location of the user.
*
* #param User $user
* #return \League\Fractal\Resource\Collection|\League\Fractal\Resource\NullResource
*/
public function includeFavouriteLocations(User $user)
{
$fav_locations = $user->favouriteLocations;
return $fav_locations
? $this->collection($fav_locations, new FavouriteLocationsTransformer)
: $this->null();
}
}
but getting error this
Type of App\Transformers\User\UserTransformer::$availableIncludes must be array (as in class League\Fractal\TransformerAbstract)
{
"success": false,
"message": "Type of App\\Transformers\\User\\UserTransformer::$availableIncludes must be array (as in class League\\Fractal\\TransformerAbstract)",
"status_code": 500,
"code": 64,
"debug": {
"line": 15,
"file": "/home/payeazyc/public_html/tagxi/app/Transformers/User/UserTransformer.php",
"class": "Symfony\\Component\\Debug\\Exception\\FatalErrorException",
"trace": [
"#0 {main}"
]
}
}

Since starting from PHP8.* types system become more stricter, and recent version focused on the language design, some of the old principles wont work as you used to them.
In you case, look at the parent class (Transformer::class), there you will find that property $availableIncludes declared with a type of array.
In your child class( UserTransformer::class) this declaration missing on type hint level, and it causes this exception. To fix it simply add a type to your array explicitly (no doc blocs and annotations). the end result will look:
class UserTransformer extends Transformer
{
protected array $availableIncludes = [
'roles','onTripRequest','metaRequest','favouriteLocations'
];

Related

CakePHP 4.2 Annotate: incorrect app namespace

I'm using CakePHP version 4.2 and am noticing some odd behavior from the annotate script that comes bundled with the API. For one component, the annotate script wants to default to the App\ domain that is CakePHP's default. I've changed the application name so most other classes default to the correct application name. But not this one script and so far, only for this one file.
I've included the body of the component, for review, below. You can see that the #method annotation uses the App\ domain. The trouble comes in when I use PHPStan to analyze my code. If I leave the annotation as is, PHPStan will tell me:
------ --------------------------------------------------------------------------------------------------------------------------------------------------------------
Line src/Controller/Component/CartManagerComponent.php
------ --------------------------------------------------------------------------------------------------------------------------------------------------------------
43 Property Visualize\Controller\Component\CartManagerComponent::$Controller (Visualize\Controller\AppController) does not accept App\Controller\AppController.
44 Call to method loadModel() on an unknown class App\Controller\AppController.
💡 Learn more at https://phpstan.org/user-guide/discovering-symbols
------ --------------------------------------------------------------------------------------------------------------------------------------------------------------
The file itself doesn't use the App\ domain anywhere. I'm not sure where to look for the script to figure out whats wrong. Here is the body of my component in case you see something I do not:
<?php
declare(strict_types=1);
namespace Visualize\Controller\Component;
use Authorization\Identity;
use Cake\Controller\Component;
use Cake\Log\Log;
/**
* CartManager component
*
* #method \App\Controller\AppController getController()
* #property \Visualize\Controller\AppController $Controller
* #property \Visualize\Model\Table\CartsTable $Carts
*/
class CartManagerComponent extends Component
{
/**
* Default configuration.
*
* #var array
*/
protected $_defaultConfig = [];
/**
* #var \Visualize\Controller\AppController
*/
protected $Controller;
/**
* #var \Visualize\Model\Table\CartsTable
*/
protected $Carts;
/**
* #param array $config The current configuration array
* #return void
*/
public function initialize(array $config): void
{
parent::initialize($config);
$this->Controller = $this->getController();
$this->Controller->loadModel('Carts');
}
/**
* Returns the most recent active cart.
*
* #param \Authorization\Identity $user The User entity.
* #return array|\Cake\Datasource\EntityInterface|null
* #noinspection PhpUnnecessaryFullyQualifiedNameInspection
*/
public function getUserCart(Identity $user)
{
$cart = $this->Controller->Carts->newEmptyEntity();
if (!empty($this->Controller->Carts) && is_a($this->Controller->Carts, '\Visualize\Model\Table\CartsTable')) {
$query = $this->Controller->Carts->find('userCart', ['user_id' => $user->getIdentifier()]);
if (!$query->isEmpty()) {
$cart = $query->first();
} else {
$cart->set('user_id', $user->getIdentifier());
$this->Controller->Carts->save($cart);
}
if (is_object($cart) && is_a($cart, '\Cake\Datasource\EntityInterface')) {
$session = $this->Controller->getRequest()->getSession();
$session->write('Cart.id', $cart->id);
}
}
return $cart;
}
/**
* Abandons carts
*
* #param int $user_id The associated user ID
* #param int $cart_id The current cart ID
* #return void
*/
public function pruneCarts(int $user_id, int $cart_id): void
{
if (!empty($this->Controller->Carts) && is_a($this->Controller->Carts, '\Visualize\Model\Table\CartsTable')) {
// Find all the carts we didn't just create:
$userCarts = $this->Controller->Carts->find('all', ['fields' => ['id', 'user_id', 'cart_status']])
->where([
'id !=' => $cart_id,
'user_id' => $user_id,
'cart_status' => 'active',
]);
if (!$userCarts->isEmpty()) {
$count = 0;
foreach ($userCarts as $cart) {
if ($count < 5) {
$record = $this->Controller->Carts->newEmptyEntity();
$record = $this->Controller->Carts->patchEntity($record, $cart->toArray());
$record->set('id', $cart->id);
$record->set('cart_status', ABANDONED_CART);
if (!$this->Controller->Carts->save($record)) {
Log::alert('Error abandoning cart');
}
} else {
$this->Controller->Carts->delete($cart);
}
$count++;
}
}
}
}
}

Laravel - Show data from a specific user

I'm trying to create a listing that will only show lyrics from the logged user, but no succeed. Need help please.
Sorry for the image link, but my reputation is still low to add images.
As you can see I have two lyrics menus, one is already accessible only for admin users and the other to show the lyrics list for authenticated user.
How can I do that?
LyricController
{
public function __construct(){
$this->middleware('auth');
$this->middleware('can:admin-content');
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$lyrics = Lyric::orderBy('lyric', 'ASC')->paginate('10');
return view('admin.lyrics.index', [
'lyrics' => $lyrics,
]);
}
/**
* Show the form for creating a new resource
*
* #return \Illuminate\Http\Response
*/
public function create()
{
// load the create form (app/views/lyrics/create.blade.php)
return view('admin.lyrics.create');
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$data = $request->only([
'title',
// 'artist',
'info',
'video_url',
'lyric'
]);
$data['slug'] = Str::slug($data['title'], '-');
$validator = Validator::make($data, [
'title' => ['required', 'string', 'max:100'],
'slug' => ['required', 'string', 'max:100', 'unique:lyrics'],
// 'artist' => ['required', 'string', 'max:200'],
'info' => ['string', 'max:100'],
'video_url' => ['required', 'string', 'max:100', 'unique:lyrics'],
'lyric' => ['required', 'string'],
]);
if ($validator->fails()) {
return redirect()->route('lyrics.create')
->withErrors($validator)
->withInput();
}
// $artist = new Singer;
// $artist->artist = $data['artist'];
// $artist->save();
$lyric = new Lyric;
$lyric->title = trim($data['title']);
$lyric->slug = $data['slug'];
$lyric->info = $data['info'];
$lyric->video_url = $data['video_url'];
$lyric->lyric = $data['lyric'];
$lyric->save();
Session::flash('message', 'Música adicionada com sucesso!');
return redirect()->route('lyrics.index');
}
/**
* Display the specified resource
*
*
.
*
* #param \App\Lyric $lyric
* #return \Illuminate\Http\Response
*/
public function show($id)
{
$lyric = Lyric::find($id);
return view('admin.lyrics.show', [
'lyric' => $lyric
]);
}
/**
* Show the form for editing the specified resource.
*
* #param \App\Lyric $lyric
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
$lyric = Lyric::find($id);
if ($lyric) {
return view('admin.lyrics.edit', [
'lyric' => $lyric
]);
}
return redirect()->route('lyrics.index');
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param \App\Lyric $lyric
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$lyric = Lyric::find($id);
if ($lyric) {
$data = $request->only([
'title',
// 'artist',
'info',
'video_url',
'lyric'
]);
if ($lyric['title'] !== $data['title']) {
$data['slug'] = Str::slug($data['title'], '-');
$validator = Validator::make($data, [
'title' => ['required', 'string', 'max:100'],
'info' => ['string', 'max:100'],
'video_url' => ['required', 'string', 'max:100', 'url'],
'slug' => ['required', 'string', 'max:100', 'unique:lyrics'],
'lyric' => ['string'],
]);
} else {
$validator = Validator::make($data, [
'title' => ['required', 'string', 'max:100'],
'info' => ['string', 'max:100'],
'video_url' => ['required', 'string', 'max:100', 'url'],
'lyric' => ['string'],
]);
}
if ($validator->fails()) {
return redirect()->route('lyrics.edit', [
'lyric' => $id
])
->withErrors($validator)
->withInput();
}
$lyric->title = trim($data['title']);
$lyric->info = $data['info'];
$lyric->video_url = $data['video_url'];
$lyric->lyric = $data['lyric'];
if (!empty($data['slug'])) {
$lyric->slug = $data['slug'];
}
$lyric->save();
}
Session::flash('message', 'Música alterada com sucesso!');
return redirect()->route('lyrics.index');
}
/**
* Remove the specified resource from storage.
*
* #param \App\Lyric $lyric
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
$lyric = Lyric::find($id);
$lyric->delete();
Session::flash('message', 'Música excluída com sucesso!');
return redirect()->route('lyrics.index');
}
Edit: I have just added foreign key to the Users Migration as suggested
Route: web.php
Route::get('/', 'Site\HomeController#index')->name('home');
Auth::routes();
Route::prefix('painel')->group(function(){
Route::get('/', 'Admin\HomeController#index')->name('admin');
/* Login Routing */
Route::get('/login', 'Admin\Auth\LoginController#index')->name('login');
Route::post('/login', 'Admin\Auth\LoginController#authenticate');
/* Logout Route */
Route::post('/logout', 'Admin\Auth\LoginController#logout')->name('logout');
Route::get('/logout', 'Admin\Auth\LoginController#logout')->name('logout-get');
/* Register Routing */
Route::get('/register', 'Admin\Auth\RegisterController#index')->name('register');
Route::post('/register', 'Admin\Auth\RegisterController#register');
/* Users Routing */
Route::resource('/users', 'Admin\UserController');
/* Profile Routing */
Route::get('/profile', 'Admin\ProfileController#index')->name('profile');
Route::put('/profilesave', 'Admin\ProfileController#save')->name('profile.save');
/* Lyrics Routing */
Route::resource('/lyrics', 'Admin\LyricController');
});
User.php (model):
public function lyrics()
{
return $this->hasMany(Lyric::class)->withTimestamps();
}
Lyric.php (model):
protected $guarded = ['id', 'singer_id', 'created_at', 'updated_at'];
public function singer()
{
return $this->belongsTo(Singer::class)->withTimestamps();
}
public function user()
{
return $this->belongsTo(User::class);
}
It would be really helpful if you could add more details in you question, but let me suggest a scenario to give you an idea of how it might be done:
Assuming you have Passport or JWT for user authentication, and that your user is logged in through api, and that you have 'Lyrics' model with user_id foreign key, you can do the following :
$logged_user = auth()->guard('api')->user();
if(isset($logged_user)){
$lyrics = Lyrics::where('user_id',$logged_user->id)->get();
//do whatever you need with lyrics
}
else{
// user not authenticated
return false;
}
More on authentication from Laravel documentation here
To show data from a logged in User. You need to establish an eloquent relationship between the User Model and The lyrics model.
Then you could just do something like $user -> lyrics()

Symfony doctrine returns objects instead of arrays

I have no idea why, but after a few (unrelated) changes all my returns are objects instead of arrays. For example:
ReceiptController.php
/**
* Get all receipts for the team.
*
* #param String $id
* #return array
*
* #SWG\Response(
* response=201,
* description="Get all receipt for the team.",
* #SWG\Schema(
* type="array"
* )
* )
*/
public function getTeamReceiptsAction($id): array
{
$parameterBag = [
'teamId' => $id
];
$items = $this->manager->getAll($parameterBag);
return $items;
}
Receiptrepository
/**
* #inheritdoc
*/
public function getFilterQuery($parameterBag): QueryBuilder
{
$qb = $this
->createQueryBuilder('s')
;
if (isset($parameterBag['id'])) {
$qb->andWhere('s.id=(:id)')
->setParameter('id', $parameterBag['id']);
}
if (isset($parameterBag['teamId'])) {
$qb->andWhere('s.team=(:team)')
->setParameter('team', $parameterBag['teamId']);
}
return $qb;
}
/**
* #inheritdoc
*/
public function getAll($parameterBag): ?array
{
$qb = $this->getFilterQuery($parameterBag);
return $qb->getQuery()->getResult();
}
Returns:
{"0":{"email":"admin#benj.be","first_name"...
While i would expect [{"email":"admin#benj.be","first_name"... ?
So it returns an object with multiple objects in it instead of an array.
But that's weird, because all my functions are typed to return array's, and I don't get any errors?
try to change this:
return $qb->getQuery()->getResult();
to this:
return $qb->getQuery()->getResult(Query::HYDRATE_ARRAY);
In this mode you can retrieve results in array
Or as Tomasz Madeysk wrote try this:
return $qb->getQuery()->getArrayResult()

Symfony2 autocomplete search

How to create autocomplete in symfony2 that will load users from local database (one input) without using any bundle?
Here's my users entity :
<?php
namespace Me\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="Me\MainBundle\Repository\UsersRepository")
* #ORM\Table(name="users")
*/
class Users
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Assert\NotBlank(
* message = "Users first name field can not be blank!",
* groups={"registration"}
* )
* #Assert\Length(
* min = 3,
* minMessage = "First name must be at least 3 characters long!",
* groups={"registration","search"}
* )
* #ORM\Column(type="string", length=255, nullable=false, name="first_name")
*/
protected $firstName;
/**
* #Assert\NotBlank(
* message = "Users last name field can not be blank!",
* groups={"registration"}
* )
* #Assert\Length(
* min = 3,
* minMessage = "Last name must be at least 3 characters long!",
* groups={"registration","search"}
* )
* #ORM\Column(type="string", length=255, nullable=false, name="last_name")
*/
protected $lastName;
//relationship variables:
/**
* #ORM\OneToMany(targetEntity="UsersSkillLevel", mappedBy="userId")
**/
protected $usersSkillLevels;
public function __construct() {
$this->usersSkillLevels = new ArrayCollection();
}
//getters, setters:
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set firstName
*
* #param string $firstName
* #return Users
*/
public function setFirstName($firstName)
{
$this->firstName = $firstName;
return $this;
}
/**
* Get firstName
*
* #return string
*/
public function getFirstName()
{
return $this->firstName;
}
/**
* Set lastName
*
* #param string $lastName
* #return Users
*/
public function setLastName($lastName)
{
$this->lastName = $lastName;
return $this;
}
/**
* Get lastName
*
* #return string
*/
public function getLastName()
{
return $this->lastName;
}
/**
* Add usersSkillLevels
*
* #param \Me\MainBundle\Entity\UsersSkillLevel $usersSkillLevels
* #return Users
*/
public function addUsersSkillLevel(\Me\MainBundle\Entity\UsersSkillLevel $usersSkillLevels)
{
$this->usersSkillLevels[] = $usersSkillLevels;
return $this;
}
/**
* Remove usersSkillLevels
*
* #param \Me\MainBundle\Entity\UsersSkillLevel $usersSkillLevels
*/
public function removeUsersSkillLevel(\Me\MainBundle\Entity\UsersSkillLevel $usersSkillLevels)
{
$this->usersSkillLevels->removeElement($usersSkillLevels);
}
/**
* Get usersSkillLevels
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUsersSkillLevels()
{
return $this->usersSkillLevels;
}
}
And search form:
$searchForm = $this->createFormBuilder()
->setMethod('POST')
->add('user_name', 'text', array('label' => 'User\'s name: ','attr' => array('placeholder' => 'Enter Users first or last name')))
->add('searchUsers', 'submit', array('label' => 'Search for employee'))
->getForm();
It should pop when first or last name is written after 3 letters.
Thank you in advance
I think this will help you:
Two things you need to do:
1) Create a Data Transformer
hich will let you use an input field instead of the default dropdown to the linked entity.
The Data Transformer basically transforms your input (in your case a username string) to actual user object that you can store with your entity. It will let you define an input field instead of the default dropdown to the linked entity. Have a look at the documentation, it's pretty straight forward.
2) Create the Ajax autocomplete
This can be done using any library you want (jQuery, Prototype etc.) on the client side, and server side you handle this in your Controller action and replies with either JSON or a rendered template. There are plenty of tutorials for this out there. The Ajax result could include a link to create a new user, if none is found.
The Data Transformer is what you need to focus on, and I would get that working before working on the UI.
Refer bellow :
How to add an autocomplete field in forms Symfony2?

Creating ZF2 module sub directories for Form , Service & InputFilter folders

I am receiving the following error
While attempting to create memberformmembernextpasswordchange(alias: Member\Form\member\NextPasswordChange) an invalid factory was registered for this instance type.
I created the following file structure ( with sub directories for Forms, Input Filters and Services ) to make it easier for long term maintenance since each section of the Member module will have so much content:
[root#localhost src]$ find . -type d
.
./Member
./Member/Form
./Member/Form/member
./Member/Form/member/Factory
./Member/Controller
./Member/Controller/Factory
./Member/Service
./Member/Service/Form
./Member/Service/Form/Factory
./Member/Service/Factory
./Member/InputFilter
./Member/InputFilter/member
But I haven't been able to figure out how to "link" the files the sub directories contain. Is this even possible?
Within module.config.php I have
'form_elements' => [
'factories' => [
'Member\Form\member\NextPasswordChange' => 'Member\Form\member\Factory\NextPasswordChangeFactory',
],
],
'input_filters' => [
'invokables' => [
'Member\InputFilter\member\NextPasswordChange' => 'Member\InputFilter\member\NextPasswordChange',
]
],
'service_manager' => [
'factories' => [
'Member\Service\Member' => 'Member\Service\Factory\MemberFactory',
'Member\Service\Form\NextPasswordChange' => 'Member\Service\Form\Factory\NextPasswordChangeFactory',
]
],
Within MemberControllerFactory I have
/**
* #param ServiceLocatorInterface $serviceLocator
*
* #return MemberController
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
/**
* #var \Zend\ServiceManager\ServiceLocatorAwareTrait $serviceLocator
*/
$sl = $serviceLocator->getServiceLocator();
/**
* #var \Member\Form\member\NextPasswordChange $formNextPasswordChange
*/
$formNextPasswordChange = $sl->get('FormElementManager')
->get('Member\Form\member\NextPasswordChange');
/**
* #var \Member\Service\Member $serviceMember
*/
$serviceMember = $sl->get('Member\Service\Member');
/**
* #var \Member\Service\Form\NextPasswordChange $serviceNextPasswordChange
*/
$serviceNextPasswordChange = $sl->get('Member\Service\Form\NextPasswordChange');
return new MemberController(
$formNextPasswordChange,
$serviceMember,
$serviceNextPasswordChange
);
}
The header section of MemberController contains
namespace Member\Controller;
use Member\Form\member\NextPasswordChange as FormNextPasswordChange;
use Member\Service\Member as ServiceMember;
use Member\Service\Form\NextPasswordChange as ServiceNextPasswordChange;
use Zend\Http\Request;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
/**
* Class MemberController
*
* #package Member\Controller
*
* #method Request getRequest()
*/
class MemberController extends AbstractActionController
{
/**
* #var FormNextPasswordChange $formNextPasswordChange
*/
private $formNextPasswordChange;
/**
* #var ServiceMember $serviceMember
*/
private $serviceMember;
/**
* #var ServiceNextPasswordChange $serviceNextPasswordChange
*/
private $serviceNextPasswordChange;
/**
* #param FormNextPasswordChange $formNextPasswordChange
* #param ServiceMember $serviceMember
*/
public function __construct(
FormNextPasswordChange $formNextPasswordChange,
ServiceMember $serviceMember,
ServiceNextPasswordChange $serviceNextPasswordChange
)
{
$this->formNextPasswordChange = $formNextPasswordChange;
$this->serviceMember = $serviceMember;
$this->serviceNextPasswordChange = $serviceNextPasswordChange;
}

Resources