typo3 flow: variable in repository - doctrine

I´d like to use a variable in a typo3 flow repository. With
$letter = $_POST['someVariable'];
it works with my following Repository:
public function findLetter() {
$letter = $_POST['letter'];
$query = $this->createQuery();
$query->matching(
$query->like('name', $letter)
);
return $query->execute();
}
I read that it should also be possible in typo3 flow to get variables by
$letter = $this->request->getArgument('someVariable');
but this doesn´t work for me; I get the following error:
#1: Notice: Undefined property: ......\Domain\Repository\MitgliedRepository::$request in /var/www/apps/flow/Data/Temporary/Development/Cache/Code/Flow_Object_Classes/..._..._Domain_Repository_...Repository.php line 96
line 96 in ...Repository is that:
$letter = $this->request->getArgument('letter');
Does anybody know, what I´m doing wrong?

I got it:
My Controller now looks linke that:
/**
* #return void
* #param string $letter
*/
public function letterAction($letter) {
$this->view->assign('mitglieder', $this->mitgliedRepository->findLetter($letter));
}
And my Repository looks like that:
/**
* #return string
*/
public function findLetter($letter) {
$query = $this->createQuery();
$query->matching(
$query->like('name', $letter)
)
->setOrderings(array('name' => \TYPO3\Flow\Persistence\QueryInterface::ORDER_ASCENDING));
return $query->execute();
}

Related

Operation without entity

I've been looking for a solution for a while but none of the one I find really allows me to do what I want. I would just like to create routes that don't necessarily require an entity or id to be used. Can you help me the documentation is not clear to do this.
Thank you beforehand.
As you can read in the General Design Considerations, just make an ordinary PHP class (POPO). Give it an ApiResource annontation like this:
* #ApiResource(
* collectionOperations={
* "post"
* },
* itemOperations={}
* )
Make sure the folder your class is in is in the paths list in api/config/packages/api_platform.yaml. There usually is the following configuration:
api_platform:
mapping:
paths: ['%kernel.project_dir%/src/Entity']
You should add your path if your class is not in the Entity folder.
Api Platform will expect json to be posted and try to unserialize it into an instance of your class. Make a custom DataPersister to process the instance, for example if your class is App\ApiCommand\Doit:
namespace App\DataPersister;
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
use App\ApiCommand\Doit;
use App\ApiResult\DoitResult;
final class DoitDataPersister implements ContextAwareDataPersisterInterface
{
public function supports($data, array $context = []): bool
{
return $data instanceof Doit;
}
public function persist($data, array $context = [])
{
// code to process $data
$result = new DoitResult();
$result->description = 'Hello world';
return $result;
}
public function remove($data, array $context = [])
{
// will not be called if you have no delete operation
}
}
If you need Doctrine, add:
public function __construct(ManagerRegistry $managerRegistry)
{
$this->managerRegistry = $managerRegistry;
}
See Injecting Extensions for how to use it.
Notice that the result returned by ::persist is not an instance of Doit. If you return a Doit api platform will try to serialize that as the result of your operation. But we have marked Doit as an ApiResource so (?) api platform looks for an item operation that can retrieve it, resulting in an error "No item route associated with the type App\ApiCommand\Doit". To avoid this you can return any object that Symfonies serializer can serialize that is not an ApiResource. In the example an instance of DoitResult. Alternatively you can return an instance of Symfony\Component\HttpFoundation\Response but then you have to take care of the serialization yourself.
The post operation should already work, but the swagger docs are made from metadata. To tell api platform that it should expect a DoitResult to be returned, change the #ApiResource annotation:
* collectionOperations={
* "post"={
* "output"=DoitResult::class
* }
* },
This will the add a new type for DoitResult to the swagger docs, but the descriptions are still wrong. You can correct them using a SwaggerDecorator. Here is one for a 201 post response:
namespace App\Swagger;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
final class SwaggerDecorator implements NormalizerInterface
{
private $decorated;
public function __construct(NormalizerInterface $decorated)
{
$this->decorated = $decorated;
}
public function normalize($object, string $format = null, array $context = [])
{
$summary = 'short explanation about DoitResult';
$docs = $this->decorated->normalize($object, $format, $context);
$docs['paths']['/doit']['post']['responses']['201']['description'] = 'Additional explanation about DoitResult';
$responseContent = $docs['paths']['/doit']['post']['responses']['201']['content'];
$this->setByRef($docs, $responseContent['application/ld+json']['schema']['properties']['hydra:member']['items']['$ref'],
'description', $summary);
$this->setByRef($docs, $responseContent['application/json']['schema']['items']['$ref'],
'description', $summary);
return $docs;
}
public function supportsNormalization($data, string $format = null)
{
return $this->decorated->supportsNormalization($data, $format);
}
private function setByRef(&$docs, $ref, $key, $value)
{
$pieces = explode('/', substr($ref, 2));
$sub =& $docs;
foreach ($pieces as $piece) {
$sub =& $sub[$piece];
}
$sub[$key] = $value;
}
}
To configure the service add the following to api/config/services.yaml:
'App\Swagger\SwaggerDecorator':
decorates: 'api_platform.swagger.normalizer.api_gateway'
arguments: [ '#App\Swagger\SwaggerDecorator.inner' ]
autoconfigure: false
If your post operation is not actually creating something you may not like the 201 response. You can change that by specifying the response code in the #ApiResource annotation, for example:
* collectionOperations={
* "post"={
* "output"=DoitResult::class,
* "status"=200
* }
* },
You may want to adapt the SwaggerDecorator accordingly.
Creating a "get" collection operation is similar, but you need to make a DataProvider instead of a DataPersister. The chapter9-api branch of my tutorial contains an example of a SwaggerDecorator for a collection response.
Thanks you for answer. I had some information but not everything. I will try the weekend.

Impossible to get my $params in Laravel scope

I'm new in Laravel and I try to do a list a table. On this list I have some filters.
I try to use scope but It doesn't work.
In my controller I have :
class GrillesController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index(request $request)
{
$query = DB::table('grilles')
->join('compets as CO','CO.id','=','gri_compet_id')
->join ('journees as JO', 'JO.id','=','gri_journee_id')
->select('com_nm_logo','jou_l_journee_c','grilles.*')
->where('com_c_st','A')
->orderbyRaw('gri_d_deb,gri_h_deb,com_n_ord_aff');
$params = $request->except('_token');
$grilles = Grilles::FilterListe($query,$params)->get();
In my model :
public function scopeFilterListe($query,$params)
{
$value = $params['filter_compets'];
$query->where('gri_compet_id','=',$value);
return $query;
}
In scopeFilterListe in the model, I'd like to get all my variable of my URL to build my where clause.
http://xxx.fr/grilles?_token=DMcay7SkDc1QeFlxRPMqT4DTGJXdgcXRbVbCNRvo&filter_compets=1&filter_etatparis=3&filter_periode=
I tried a lot of things, but I always have this error:
"Cannot use object of type Illuminate\Database\Query\Builder as
array"
It comes from : $value = $params['filter_compets'];
If I write $value=1, it works...(even if I have another problem as the data supposed to come from
->join('compets as CO','CO.id','=','gri_compet_id')
->join ('journees as JO', 'JO.id','=','gri_journee_id')
are not displayed..
What is the problem for my scope ?
Thanks a lot for your help.
I think that you need dynamic scope. Please find documentation here.
Herewith your modified script.
public function scopeOfFilterListe($query,$value)
{
$query->where('gri_compet_id','=',$value);
return $query;
}
$query = DB::table('grilles')
->join('compets as CO','CO.id','=','gri_compet_id')
->join ('journees as JO', 'JO.id','=','gri_journee_id')
->select('com_nm_logo','jou_l_journee_c','grilles.*')
->where('com_c_st','A')
->orderbyRaw('gri_d_deb,gri_h_deb,com_n_ord_aff')
;
$params = $request->except('_token');
$grilles = Grilles::ofFilterListe($params['filter_compets'])->get();

Curl returning null response when run from artisan command for cron job

Trying to run an API which will give me the updated temperature and humidity values but the curl function is not working as it gives a NULL reponse and throws error. running the from the terminal to test it
code:
class updateTempHumHourly extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'update:temphum';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Update temperature and humidity readings hourly';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$options = array(
'cluster' => 'ap2',
'useTLS' => true
);
$pusher = new \Pusher\Pusher(
'osdifnerwion4iownfowinf',
'dofhewofhewofnowenfid',
'7asdkland',
$options
);
$thinkers = t::where('user_id', '!=' , NULL)->where('thinker_status',1)->get();
foreach($thinkers as $t)
{
$temp = [
'action'=>'list_slave',
'mac'=> $t->thinker_MAC,
'type' => 'all',
'appkey' => 'nope'
];
json_encode($temp);
$response = Curl::to('http://103.31.82.46/open/open.php')
->withContentType('application/json')
->withData($temp)
->asJson(true)
->withHeader('Postman-Token: d5988618-676e-430c-808e-7e2f6cec88fc')
->withHeader('cache-control: no-cache')
->post();
foreach($response['slaves'] as $s)
{
if(array_key_exists("temp",$s) && array_key_exists("hum",$s))
{
$slave = sd::where("connected_thinker_MAC",$response['mac'])->where("device_id",$s['slave_id'])->first();
$slave->temperature = $s['temp'];
$slave->humidity = $s['hum'];
$slave->save();
$array = [];
$array['temperature'] = $s['temp'];
$array['humidity'] = $s['hum'];
$array['id'] = $s['slave_id'];
$pusher->trigger($t->user_id."-channel","s-event",$array);
\App\helper\log::instance()->tempHumLog($s);
}
}
}
}
}
the foreach loop throws an error that $response is equal to null. the curl function is not working from here but working fine regularly. help. i need to run this task every hour to get the average temperature and humidity.
Since you said that your code works somewhere that means that there is something wrong with your server and not the code itself probably (since it's a CURL issue).
Inside your php.ini file there is this line : extension=php_curl.dll to enable curl. Uncomment it on your server that you have the crons to make curl work. This should solve your problem.
Testing localy the api you provide us returns a 500 but if you say that it works for you i assume that this is just an example and the problem is in CURL itself.

Eloquent: querying using a non-existing column

I'm trying the following: I have two models (Pub and Schedule) related by a 1xN relationship as follows:
Pub:
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function pubSchedules()
{
return $this->hasMany(Schedule::class);
}
Schedule:
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function pub()
{
return $this->belongsTo(Pub::class);
}
Table schedules has the following fields:
id | pub_id | week_day | opening_time | closing_time |
I use the following function to know if one pub is currently (or not) open:
/**
* #return bool
*/
public function isPubCurrentlyOpen()
{
$schedules = Schedule::where([
['pub_id', $this->id ],
['week_day', Carbon::now()->dayOfWeek],
])->get();
foreach ($schedules as $schedule){
$isOpen[] =
Carbon::now('Europe/Madrid')->between(
Carbon::now('Europe/Madrid')->setTimeFromTimeString($schedule->opening_time),
Carbon::now('Europe/Madrid')->setTimeFromTimeString($schedule->closing_time)
);
}
if(in_array(true, $isOpen)){
return true;
//return "Pub Opened";
}
return false;
//return "Pub Closed";
}
In my PubController I'd like, when the option "Filter by open pubs" is chosen if($request->openPubs == 1), to show only opened pubs isOpen ==true.
Knowing the relationships between models, how can I do it?
I'm looking for something like this:
if($request->openPubs == 1)
{
$pubs = $pubs->with('pubSchedules')->where('isOpen' == true);
}
Can you help me?
Thanks a lot!
You can do this using a "whereHas"
$openPubs = Pub::whereHas('schedule', function ($query) {
$query->where('week_day', Carbon::now()->dayOfWeek);
$query->whereRaw(
"'".Carbon::now('Europe/Madrid')->format("H:i:s")."' BETWEEN opening_time AND closing_time"
);
})->get();
This is assuming your opening time and closing time are the appropriate time format and not strings (though strings will work as well in a 24h format).
You might achieve something similar to what you are looking for by using a scope e.g.
public function scopeFilterBy($query, $filter = null) {
if ($filter == "isOpen") {
$query->whereHas('schedule', function ($query) {
$query->where('week_day', Carbon::now()->dayOfWeek);
$query->whereRaw(
"'".Carbon::now('Europe/Madrid')->format("H:i:s")."' BETWEEN opening_time AND closing_time"
);
});
}
return $query; //Not sure if this is needed
}
You could then do:
Pub::filterBy($request->openPubs ? "isOpen" : null)->get();
I don't fully understand how you are trying to accomplish this but it should be something like this
$pubs = Pub::with(['pubSchedules' => function ($query) {
$query->where('opening_time', '>' ,Carbon::now()) // make sure it's currently open
->where('closing_time', '<' ,Carbon::now()) // make sure that it's not finished already
->where('week_day', '==' ,Carbon::now()->dayOfWeek) // make sure it's today
}])->find($id);
// to get if pub is currently
if($pub->pubSchedules->count()){
//
}
you can put this code in the model (Pub) and make some changes
if you already have the object you can do this (Add it to model)
public function isPubOpen()
{
$this->load(['pubSchedules' =>
// same code in other method
]);
return (bool) $this->pubSchedules->count();
}
For small tables you could call the function isPubCurrentlyOpen for each element.
For this you would need to change your function to recieve the pub_id as a parameter:
public function isPubCurrentlyOpen($pub_id)
{
$schedules = Schedule::where([
['pub_id', $pub_id ],
['week_day', Carbon::now()->dayOfWeek],
])->get();
foreach ($schedules as $schedule){
$isOpen[] =
Carbon::now('Europe/Madrid')->between(
Carbon::now('Europe/Madrid')->setTimeFromTimeString($schedule->opening_time),
Carbon::now('Europe/Madrid')->setTimeFromTimeString($schedule->closing_time)
);
}
if(in_array(true, $isOpen)){
return true;
//return "Pub Opened";
}
return false;
//return "Pub Closed";
}
and to query the data do:
if($request->openPubs == 1)
{
// assuming $pubs is a collection instance
$pubs = $pubs->filter(function($a){
return $this->isPubCurrentlyOpen($a->id);
})
}
There's a feature in Eloquent called Eager Loading. The Eloquent ORM provides a simple syntax to query for all the Schedules that are related with this particular Pub as described below:
$pubIsOpen= $pub->schedules()
->where([
['week_day', Carbon::now()->dayOfWeek],
['opening_time' , '<' , Carbon::now('Europe/Madrid')],
['closing_time' , '>' , Carbon::now('Europe/Madrid')]
])
->count();
if($openPubCount > 0){
//PUB is open
}else{
//PUB is closed
}
If it helps to someone in the future I post my solution, thanks to #apokryfos:
Pub:
/**
* #param $pubs
* #return mixed
*/
public static function isPubCurrentlyOpen($pubs)
{
$pubs->whereHas( 'pubSchedules', function ($pubs) {
$pubs->where( 'week_day', Carbon::now()->dayOfWeek )
->whereRaw(
"'" . Carbon::now( 'Europe/Madrid' )->format( "H:i:s" ) . "' BETWEEN opening_time AND closing_time"
);
} );
return $pubs;
}
PubsController:
/**
* #param GetPubRequest $request
* #return ApiResponse
*/
public function getPubs(GetPubRequest $request)
{
$orderBy = 'id';
$order = 'asc';
$pubs = Pub::withDistance();
............
if($request->openPubs == 1)
{
$pubs = Pub::isPubCurrentlyOpen($pubs);
}
return $this->response(PubProfileResource::collection($pubs->orderBy($orderBy, $order)->paginate()));
}

Mage_Core_Exception with message 'Cannot retrieve entity config: sales/Array'

The following code runs fine under Magento 1.6 but raises a Mage_Core_Exception (message: 'Cannot retrieve entity config: sales/Array') when run under 1.5.0.1. What do I need to do to get this code running under Magento 1.5.0.1?
$results = Mage::getResourceModel('sales/order_collection');
$results->join(
array('status_key_table' => 'order_status'),
'main_table.status = status_key_table.status',
array('status_key_table.label')
);
Thank you,
Ben
If you compare the join() methods between 1.5.0.1 and 1.6.2.0:
1.5.0.1: Mage_Core_Model_Mysql4_Collection_Abstract::join()
public function join($table, $cond, $cols='*')
{
if (!isset($this->_joinedTables[$table])) {
$this->getSelect()->join(array($table=>$this->getTable($table)), $cond, $cols);
$this->_joinedTables[$table] = true;
}
return $this;
}
1.6.2.0: Mage_Core_Model_Resource_Db_Collection_Abstract::join()
public function join($table, $cond, $cols = '*')
{
if (is_array($table)) {
foreach ($table as $k => $v) {
$alias = $k;
$table = $v;
break;
...
You can see that 1.5.0.1 doesn't support aliases. Instead, it calls $this->getTable() on the first parameter you pass in -- which should be a string. So, in your case, you'll need to pass in 'sales/order_status' as the first parameter.

Resources