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'
];
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++;
}
}
}
}
}
there is a page which is updated every 5-7 seconds, and on it records from the base are updated, but moments these records are duplicated, Do not tell me why this bug can be?
is a ActiveCaller model
namespace App;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
class ActiveCaller extends Model
{
protected $fillable = ['queue', 'employee_id', 'station', 'state', 'duration',
'client_id', 'last_call'];
public function Employee()
{
return $this->belongsTo(Employee::class);
}
/**
* Convert duration attribute to acceptable format
*
* #param $value
* #return string
*/
public function getDurationAttribute($value)
{
if (empty($value))
return $value;
return $this->sec2hms($value);
}
public function getStateAttribute($value)
{
if (!empty($value))
return trim($value);
return null;
}
/**
* Convert last call attribute to acceptable format
*
* #param $value
* #return string
*/
public function getLastCallAttribute($value)
{
$data = explode("\n", $value);
$result = "";
$i = 0;
$len = count($data) - 1;
foreach ($data as $item) {
$item = str_replace("\r", "", $item);
$delimiter = "</br>";
if ($i == $len)
$delimiter = "";
if (empty($item) || (trim($item) == "No calls yet")) {
$result .= "No calls yet$delimiter";
} else {
$result .= $this->sec2hms($item) . " min. ago $delimiter";
}
$i++;
}
return $result;
}
public function getStationAttribute($value)
{
return str_replace("\r\n", "</br>", $value);
}
private function sec2hms($sec, $padHours = FALSE)
{
$timeStart = Carbon::now();
$timeEnd = Carbon::now()->addSeconds(intval($sec));
return $timeStart->diff($timeEnd)->format('%H:%I:%S');
}
}
is a AmiApiController
class AmiApiController extends Controller
{
public function fetchDashboardData()
{
$this->updateQueueState();
$activeCallers = ActiveCaller::with('Employee')
->where('old', true)
->orderBy('queue')
->orderBy('employee_id')
->orderBy('station', 'asc')
->get();
$waitingList = WaitingList::where('old', false)->get();
$waitingList = $waitingList->unique('client_id');
$charts = Chart::all()->toArray();
$chartFormatData = [
'Total' => [],
'Callers' => [],
'Queues' => [],
];
foreach ($charts as $key => $chart) {
$charts[$key]['data'] = json_decode($chart['data'], 1);
$chartFormatData[$chart['name']]['total'] = 0;
foreach ($charts[$key]['data']['statistic'] as $datum) {
// if ($datum[0] === 'Effort')
// continue;
$chartFormatData[$chart['name']]['label'][] = $datum[0];
$chartFormatData[$chart['name']]['data'][] = $datum[1];
$chartFormatData[$chart['name']]['name'] = $chart['name'];
}
$chartFormatData[$chart['name']]['total'] = array_sum($chartFormatData[$chart['name']]['data']);
// $chartFormatData[$chart['name']]['label'] = array_reverse($chartFormatData[$chart['name']]['label']);
}
return response()->json([
'activeCallers' => $activeCallers,
'charts' => $chartFormatData,
'waitingList' => $waitingList
], 200);
}
this is where we begin to check if we can update the database at this time
/**
* Check whether the database can be updated at this time
*
* - Returns True if no updates are currently being made to the database
* and the latest update was less than 5 seconds later
* -
Returns True if the update already occurs for more than 15 seconds
*
* - Returns False if an update is already in the database
* -
Returns False if the last update was within the last 5 seconds
*
* If the parameter in $ json is passed true (by default)
* the method returns the answer in JSON format
*
* If the parameter is passed false to $ json
* method returns a php-shne Boolean value
*
* #param bool $json
* #return bool|\Illuminate\Http\JsonResponse
*/
public function canWeUpdate($json = true)
{
$result = ['return' => null, 'msg' => null];
$isUpdating = Configuration::where('key', 'is_ami_data_updating')->first();
if (is_null($isUpdating)) {
Configuration::create(['key' => 'is_ami_data_updating', 'value' => 0]);
}
if ($isUpdating->value == true) {
// if an update is currently in progress
$checkingDate = Carbon::now()->addSeconds(-10);
if ($isUpdating->updated_at < $checkingDate) {
// if the update is longer than 15 seconds, we will cancel this update
$isUpdating->update(['value' => false]);
$result['return'] = true;
$result['msg'] = "Old update in database";
} else {
// if the update is less than 15 seconds, we cannot update again
$result['return'] = false;
$result['msg'] = "CURRENTLY UPDATE";
}
} else if ($isUpdating->updated_at > Carbon::now()->addSeconds(-3)) {
// if the last update was less than 5 seconds ago, we cannot update
$result['return'] = false;
$result['msg'] = "TOO EARLY";
} else {
//if the last update was more than 5 seconds ago, we allow the update
$result['return'] = true;
$result['msg'] = "OK";
}
if ($json)
return $this->simpleResponse($result['return'], $result['msg']);
return $result['return'];
}
is a method fot check if new data is in the database
/**
* A method to check if new data is in the database
*
* Returns True if validation time is less than database update time
* Returns False if validation time is longer than database update time
* Returns False if there is no data in the database
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\JsonResponse
*/
public function checkForNewData(Request $request)
{
$date = new Carbon($request->last_call);
$lastRecord = ActiveCaller::latest()->first();
if (is_null($lastRecord))
return $this->simpleResponse(false);
if ($date < $lastRecord->updated_at) {
return $this->simpleResponse(true);
} else
return $this->simpleResponse(false);
}
/**
* Method for loading table data
*
* Agents - information about active numbers in the PBX in all queues
* Waiting - information about numbers in standby mode
*
* #return \Illuminate\Http\JsonResponse
*/
public function renderAgentTable()
{
$agents = ActiveCaller::with('Employee')
->where('old', true)
->orderBy('queue')
->orderBy('station', 'asc')
->get();
$waitingList = WaitingList::all();
$agentsTable = View::make('dashboard.render.agent-table', ['agents' => $agents]);
$waitingTable = View::make('dashboard.render.waiting-list-table', ['waitingList' => $waitingList]);
$result =
[
'agents' => $agentsTable->render(),
'waiting' => $waitingTable->render(),
];
$result = array_merge($result, $this->renderDashboardChart(new Request()));
return response()->json($result);
}
/**
* Method for updating data from AMI
*
* updating data for ActiveCaller
* updating data for WaitingList
*/
public function updateQueueState()
{
if (!$this->canWeUpdate(false)) {
// dd("We can't update (large check)");
return;
}
$lastUpdateTime = ActiveCaller::latest()->first();
if ($lastUpdateTime != null)
if ($lastUpdateTime->created_at > Carbon::now()->addSeconds(-3)) {
// dd("We can't update (small check)");
return;
}
// we notice the launch of the update in the database
$isAmiDataUpdating = Configuration::where('key', 'is_ami_data_updating')->first();
$isAmiDataUpdating->update(['value' => true]);
$this->ClearOldRecords();
$queues = Queue::where('on_dashboard', '=', '1')->get()->toArray();
// we go through all the queues that are available in AMI
foreach ($queues as $queue) {
$command = new AMIQueueMemberState($queue['name']);
// we get a list of numbers and a waiting list of calls
$response = $command->handle();
$agents = $response['agents'];
$callers = $response['callers'];
//convert the waiting list to PeerList
$peerList = PeerInfo::hydrate($agents);
$employees = new Collection();
foreach ($callers as $caller) {
$caller['queue'] = $queue['name'];
WaitingList::create($caller);
}
$peerList->each(function (PeerInfo $peer) use ($employees) {
$record = Record
::where('phone', 'like', '%' . $peer->name . '%')
->where('end_date', null)
->get()->first();
$data = null;
if ($record != null) {
// check if this user already has an entry in active_callers (not old)
$active = ActiveCaller
::where('employee_id', $record['employee_id'])
->where('old', false)
->get()->first();
// if so, add him another number and
// we move on to the next iteration
if ($active != null) {
if ($this->HandleSingleActive($active, $peer->name, $peer->last_call))
return;
}
$peer->station = $record['station_name'];
$peer->employee_id = $record['employee_id'];
$a = collect($peer->toArray());
$data = $a->except(['name', 'pause'])->toArray();
$data['station'] = "$peer->station | $peer->name";
} else {
$peer->station = "- | $peer->name";
$a = collect($peer->toArray());
$data = $a->except(['name', 'pause'])->toArray();
}
ActiveCaller::create($data);
});
}
$this->updateDashboardChart();
$isAmiDataUpdating->update(['value' => false]);
}
I was wondering if there is a way to search in entity without applying any filters. For Example I would like to build a textfiled in my template where a ajax post method is calling to a controller with purpose searching the whole entity.
My code:
$user = $this->getDoctrine()
->getRepository('AppBundle:QCE_SUBD')
->find('%'.$SearchParam.'%')
->getQuery();
$DSUB = $user->getArrayResult();
dump($DSUB);
I;m not sure how the function should be written, so if some one is willing to help it will be highly appreciate :)
You should just create a function that return a JsonResponse with an array of your result.
// In your controller
/**
* #Route("/ajax_action")
*/
public function ajaxAction(Request $request)
{
// Get the posted parameter from your ajax call
$searchParam = $request->get('searchParam');
// Request your entity
$user = $this->getDoctrine()
->getRepository('AppBundle:QCE_SUBD')
->createQueryBuilder('q')
->where('q.username LIKE :searchParam')
->orWhere('q.otherColumn LIKE :searchParam')
->setParameter('searchParam', '%'.$searchParam.'%')
->getQuery();
// Check if it's an ajax call
if ($request->isXMLHttpRequest()) {
return new JsonResponse($user->getArrayResult();
}
// Return an error
throw new \Exception('Wrong call!');
}
For the search part you need to implement a full text search, here is a tutorial on how to implement it :
http://ourcodeworld.com/articles/read/90/how-to-implement-fulltext-search-mysql-with-doctrine-and-symfony-3
P.S : You should be sure of what you need in your query. If you want it to be scalable, you should take a look at better search engine method as ElasticSearch or Solr.
You can inspire yourself from the following function. It iterates dynamically through all fields of the entity and depending on the type of the field a condition is applied to the query builder:
/**
* Creates the query builder used to get the results of the search query
* performed by the user in the "search" view with a given "keyword".
*
* #param array $entityConfig
* #param string $searchQuery
* #param string|null $sortField
* #param string|null $sortDirection
* #param string|null $dqlFilter
*
* #return DoctrineQueryBuilder
*/
public function createSearchQueryBuilder(array $entityConfig, $searchQuery, $sortField = null, $sortDirection = null, $dqlFilter = null)
{
/* #var EntityManager */
$em = $this->doctrine->getManagerForClass($entityConfig['class']);
/* #var DoctrineQueryBuilder */
$queryBuilder = $em->createQueryBuilder()
->select('entity')
->from($entityConfig['class'], 'entity')
;
$queryParameters = array();
foreach ($entityConfig['search']['fields'] as $name => $metadata) {
$isNumericField = in_array($metadata['dataType'], array('integer', 'number', 'smallint', 'bigint', 'decimal', 'float'));
$isTextField = in_array($metadata['dataType'], array('string', 'text', 'guid'));
if ($isNumericField && is_numeric($searchQuery)) {
$queryBuilder->orWhere(sprintf('entity.%s = :exact_query', $name));
// adding '0' turns the string into a numeric value
$queryParameters['exact_query'] = 0 + $searchQuery;
} elseif ($isTextField) {
$searchQuery = strtolower($searchQuery);
$queryBuilder->orWhere(sprintf('LOWER(entity.%s) LIKE :fuzzy_query', $name));
$queryParameters['fuzzy_query'] = '%'.$searchQuery.'%';
$queryBuilder->orWhere(sprintf('LOWER(entity.%s) IN (:words_query)', $name));
$queryParameters['words_query'] = explode(' ', $searchQuery);
}
}
if (0 !== count($queryParameters)) {
$queryBuilder->setParameters($queryParameters);
}
if (!empty($dqlFilter)) {
$queryBuilder->andWhere($dqlFilter);
}
if (null !== $sortField) {
$queryBuilder->orderBy('entity.'.$sortField, $sortDirection ?: 'DESC');
}
return $queryBuilder;
}
The source code comes from the EasyAdminBundle.
i am using Behat 3.0 and Mink 1.6.
Those codes work with Selenium2 and Zombie, but not with Goutte:
$this->assertSession()->elementTextContains('xpath', "//div[#id='pagecontent-shop']/form/table/tbody/tr[12]/td[2]", $arg1);
$page = $this->getSession()->getPage();
$element = $page->find('xpath', "//div[#id='pagecontent-shop']/form/table/tbody/tr[12]/td[2]",)->getText();
Does anyone knows what is happening?
Did you try findById()?
e.g.
/**
* #When /^I click an element with ID "([^"]*)"$/
*
* #param $id
* #throws \Exception
*/
public function iClickAnElementWithId($id)
{
$element = $this->getSession()->getPage()->findById($id);
if (null === $element) {
throw new \Exception(sprintf('Could not evaluate element with ID: "%s"', $id));
}
$element->click();
}
e.g.
/**
* Click on the element with the provided css id
*
* #Then /^I click on the element with id "([^"]*)"$/
*
* #param $elementId ID attribute of an element
* #throws \InvalidArgumentException
*/
public function clickElementWithGivenId($elementId)
{
$session = $this->getSession();
$page = $session->getPage();
$element = $page->find('css', '#' . $elementId);
if (null === $element) {
throw new \InvalidArgumentException(sprintf('Could not evaluate CSS: "%s"', $elementId));
}
$element->click();
}
EDIT:
Example below goes thru input elements in a table and finds the ones with specific name. You need to modify it a bit though.
/**
* #Given /^the table contains "([^"]*)"$/
*/
public function theTableContains($arg1)
{
$session = $this->getSession();
$element = $session->getPage()->findAll('css', 'input');
if (null === $element) {
throw new \Exception(sprintf('Could not evaluate find select table'));
}
$options = explode(',', $arg1);
$match = "element_name";
$found = 0;
foreach ($element as $inputs) {
if ($inputs->hasAttribute('name')) {
if (preg_match('/^'.$match.'(.*)/', $inputs->getAttribute('name')) !== false) {
if (in_array($inputs->getValue(), $options)) {
$found++;
}
}
}
}
if (intval($found) != intval(count($options))) {
throw new \Exception(sprintf('I only found %i element in the table', $found));
}
}