time array converson cakephp3 - cakephp

I have a simple question as I just want to convert the time (in array format) to a 24hr time string. The issue I get the time from user input and it places it in an array object which the formatting isnt working .
I couldnt find the answer from https://book.cakephp.org/3.0/en/core-libraries/time.html#conversion
time format inputted from a form
'start_time' => [
'hour' => '02',
'minute' => '00',
'meridian' => 'pm'
],
view//
echo $this->Form->input('start_time', ['label' => 'Class Start Time','type' => 'time',
'interval' => 5,'timeFormat'=>12,'value'=>$startTime,]);
//controller
if ($this->request->is('post')) {
debug($this->request->data['start_time']->i18nFormat('HH:mm:ss'));//cant use on an array
//this works but is there a better way
$startTime = $this->request->data['start_time']['hour'].":".$this->request->data['start_time']['minute']." ".
$this->request->data['start_time']['meridian'];
$this->request->data['start_time'] = date("H:i:s", strtotime( $startTime));
debug($this->request->data);

You should create a Time instance, because $this->request->data['start_time'] is not formated:
use Cake\I18n\Time;
...
$StartTimeHour = $this->request->data['start_time']['hour'];
$StartTimeMinute = $this->request->data['start_time']['minute'];
$StartTimeMeridian = $this->request->data['start_time']['meridian'];
$time = new Time("${StartTimeHour}:${StartTimeMinute} ${StartTimeMeridian}");
echo $time->i18nFormat('HH:mm:ss');
*Tested and working.

Related

Drupal - Get custom taxonomy fields

I am trying to get a custom field assigned to taxonomy. I have tried this:
$vid = 'zeme';
$terms =\Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($vid);
$terms is now storing all the terms from the vocabulary called 'zeme'. The problem is when I print this variable, it doesnt show the custom field that I need to get.
Any idea how can I get this custom field?
My code looks like this:
$vid = 'zeme';
$terms =\Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($vid);
foreach ($terms as $term) {
$term_data[] = array(
'id' => $term->tid,
'name' => $term->name
);
}
Here is the loadTree function official documentation :
TermStorage::loadTree
When you use the loadTree function, it will only get you the minimal datas to save execution time. You can see there is a $load_entities parameter set to false by default.
bool $load_entities: If TRUE, a full entity load will occur on the
term objects. Otherwise they are partial objects queried directly from
the {taxonomy_term_data} table to save execution time and memory
consumption when listing large numbers of terms. Defaults to FALSE.
So if you want to get all the datas of each of your taxonomy terms, you have to set $load_entities to true.
$vid = 'zeme';
$terms =\Drupal::entityTypeManager()
->getStorage('taxonomy_term')
->loadTree($vid, 0, null, true);
Found this way from this post Get custom fields assigned to taxonomy:
$contact_countries = \Drupal::service('entity_type.manager')->getStorage("taxonomy_term")->loadTree('contact_country');
$terms = array();
foreach($contact_countries as $contact_countrie) {
$terms[] = array(
'contact_country' => $contact_countrie->name,
'contact_phone' => \Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($contact_countrie->tid)->get('field_phone')->getValue()[0]['value'],
'contact_flag' => \Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($contact_countrie->tid)->get('field_category_flag')->entity->uri->value,
);
}
Very usefull!
public function getTaxonomyBuild(){
$terms = \Drupal::service('entity_type.manager')->getStorage("taxonomy_term")->loadTree('faq_sec');
foreach($terms as $term) {
$term_data[] = array(
'name' => $term->name,
'img' => file_create_url(\Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($term->tid)->get('field_sec_img')->entity->uri->value),
);
}
return $term_data;
}
good solution

Contain complex query date_format and between

Code Update 2017/07/20
I followed the recommendations of #Arcesilas (here) with the use of date_format of MySQL.
I upgraded my data structure by merging start_month and start_day (ex 2017-01-16 = 0116)
[...]
->contain([
'Bookings',
'Amenities',
'Periodicities' => function ($q) use ($check_in, $check_out) {
$start = $q->func()->date_format([
'Periodicities.start' => $check_in->format('Ymd'),
"'%m%d'" => 'literal'
]);
$end = $q->func()->date_format([
'Periodicities.end' => $check_out->format('Ymd'),
"'%m%d'" => 'literal'
]);
return $q
->where(function ($exp) use ($start) {
$exp->between($start, 'Periodicities.start', 'Periodicities.end');
return $exp;
})
->orWhere(function ($exp) use ($end) {
$exp->between($end, 'Periodicities.start', 'Periodicities.end');
return $exp;
});
}
])
[...]
Cakephp SQL Log
SELECT
PeriodicitiesRooms.id AS `Periodicities_CJoin__id`,
PeriodicitiesRooms.periodicity_id AS `Periodicities_CJoin__periodicity_id`,
PeriodicitiesRooms.room_id AS `Periodicities_CJoin__room_id`,
PeriodicitiesRooms.price AS `Periodicities_CJoin__price`,
Periodicities.id AS `Periodicities__id`,
Periodicities.name AS `Periodicities__name`,
Periodicities.start AS `Periodicities__start`,
Periodicities.end AS `Periodicities__end`,
Periodicities.price AS `Periodicities__price`,
Periodicities.modified AS `Periodicities__modified`
FROM
periodicities Periodicities
INNER JOIN periodicities_rooms PeriodicitiesRooms ON Periodicities.id = (
PeriodicitiesRooms.periodicity_id
)
WHERE
(
date_format('20170726', '%m%d') BETWEEN 'Periodicities.start'
AND 'Periodicities.end'
OR (
PeriodicitiesRooms.room_id in ('1', '2', '3')
AND date_format('20170720', '%m%d') BETWEEN 'Periodicities.start'
AND 'Periodicities.end'
)
)
This does not give me any more result because ORM of CakePHP adds apostrophes (') to the end of BETWEEN' Periodicities.start 'AND' Periodicities.end'
If in my database I paste the CakePHP query without the apostrophes (') it works. Do you have any idea what changes to make to the end of my query so that it looks like this: BETWEEN 'Periodicities.start' AND 'Periodicities.end' to BETWEEN Periodicities.start AND Periodicities.end ?
'SELECT * FROM periodicities WHERE date_format(' . $check_in->format('Ymd') . ', '%m%d') BETWEEN start AND end'
EDIT
From your comment I see you don't want to store years because the year is not relevant.
In that case, you can still store all your dates as a specific year and then hard code that year into the query. I have modified the query to use year 2000.
ORIGINAL
The conversation is unclear to me but I will attempt to answer the question I believe you are asking.
It appears you want to know how to find Periodicities between the checkin time or Periodicities between the checkout time.
It also appears you want to know the best way to store the dates.
Just store the dates as dates. No need to make it complicated
Between is also overly complicated.
This will do what you need it to do without being confusing.
[...]
->contain([
'Bookings',
'Amenities',
'Periodicities' => function ($q) use ($check_in, $check_out) {
$q->where([
'Periodicities.start >' => $check_in->format('2000-m-d'),
'Periodicities.end <' => $check_in->format('2000-m-d')
]);
$q->orWhere([
'Periodicities.start >' => $check_out->format('2000-m-d'),
'Periodicities.end <' => $check_out->format('2000-m-d')
]);
return $q;
}
])
[...]
I solved my problem with this query :
->contain([
'Bookings',
'Amenities',
'Periodicities' => function ($q) use ($check_in, $check_out) {
$q->where(function ($exp) use ($check_in, $check_out) {
$exp->gte('Periodicities.start', $check_in->format('md'));
$exp->lte('Periodicities.end', $check_out->format('md'));
});
return $q;
}
])
I keep storing in database dates with the month and day md format
Ex: 0901 < 1030
01 September < 30 October

How to save multidimensional array in Laravel

Good afternoon !
I am creating a private chat , and I get the first objective , get the message and users with the following code.
public function getEnviarMensajes($id,$identificador){
$user = User::find($identificador);
$idReceptor = $user->id;
$idEmisor = Auth::user()->id;
$mesageuser = MessageUser::with('user')->with('message')->get();
$name = [];
$content = [];
foreach($mesageuser as $users){
foreach($users->message as $mensajes){
if($users->user->id==$idEmisor){
$name[] = $users->user->name;
echo "<p>";
$content[] = $mensajes->contenido;
echo "<p>";
echo $mensajes->created_at;
echo "<p>";
}
if($users->user->id==$idReceptor){
$name[] = $users->user->name;
echo "<p>";
$content[] = $mensajes->contenido;
echo "<p>";
echo $mensajes->created_at;
echo "<p>";
}
}
}
However , I have a problem , this results i need to "join" , in many ocasions I used an array , but in this case ? How I can save differents rows in Laravel ? , also I need to sort this content for datetime row.
Could anyone helps to me ?
I think you can cut your code at this way:
$mesageuser = MessageUser::with('user')->with('message')->get();
$messages = [];
foreach($mesageuser as $users){
foreach($users->message as $mensajes){
$messages[] = [
'nombre' => $users->user->name,
'contenido' => $mensajes->contenido,
'creado' => $mensajes->created_at,
'emisor' => ($users->user->id==$idEmisor) // true or false
];
}
}
return view('chat', ['messages' => $messages]);
The two if statements are useless because inside of them the code is the same. And I had used an multidimensional array in order to store all the messages with the following structure:
[
[
'nombre' => 'Marta',
'contenido' => 'Hola',
'creado' => '24/03/2015',
'emisor' => false
],
[
'nombre' => 'Salomé',
'contenido' => 'adiós',
'creado' => '24/03/2015',
'emisor' => true
]
]
If you want, for example, order by date, then edit your query:
$mesageuser = MessageUser::with('user')->with(['message' => function($query){
$query->orderBy('created_at', 'desc');
}])->get();

SilverStripe 3.1 loop associative array

In SilverStripe 3.1 I have a function that loops through an array and outputs its contents.
The output it gives me is:
Layout: John
Strategy: John
Management: Martin
In this example John has more than one job.
I would like to group the jobs if a person has more than one job.
This is my desired Output:
Layout and Strategy: John
Management: Martin
//$InfoFieldArray = array('Layout' => 'John', 'Strategy' => 'John', 'Management' => 'Martin');
public function createInfoFields($InfoFieldArray){
$Info = ArrayList::create();
foreach($InfoFieldArray as $key => $value ){
$fields = new ArrayData(array('FieldName' => $key, 'Value' => $value));
$Info->push($fields);
}
return $Info;
}
How do I alter my function to achieve my desired output?
One possible solution to that is by restructuring the data before adding it to the ArrayList.
public function createInfoFields($InfoFieldArray)
{
$info = array();
foreach ($InfoFieldArray as $job => $person)
{
if (!isset($info[$person]))
{
$info[$person] = array();
}
$info[$person][] = $job;
}
$result = ArrayList::create();
foreach ($info as $person => $jobs)
{
$fields = new ArrayData(array('FieldName' => implode(' and ', $jobs), 'Value' => $person));
$result->push($fields);
}
return $result;
}
What I have done is go over the array of jobs and the person assigned and flipped it the other way around, so I have an array of people with a list of jobs. This allows me to then just call implode in PHP, joining the various jobs by the word and.
There are some potential drawbacks, if there are two people named "John", they will be treated as one as I am using the name as the array key.
Also, if there are three jobs for a person, it will list it like "Layout and Strategy and Management". To avoid that, we need to modify the second foreach loop in my code to something like this:
foreach ($info as $person => $jobs)
{
$jobString = null;
if (count($jobs) > 1)
{
$jobString = implode(', ', array_slice($jobs, 0, -1)) . ' and ' . array_pop($jobs);
}
else
{
$jobString = $jobs[0];
}
$fields = new ArrayData(array('FieldName' => $jobString, 'Value' => $person));
$result->push($fields);
}
When there is more than 1 job for a person, we want to implode (glue together) the array pieces for the $jobs array however we don't want the last element at this point. Once array is glued together, we append with with and along with the last item.

Using array for MySQL Select Statement

Apologies in advance if i use the wrong definition of a word...I am using SimpleCart to pass $.Post variables to a PHP page. If i print the array i get
Array ( [currency] => CAD [shipping] => 0 [tax] => 1.69 [taxRate] => 0.13 [itemCount] => 3 [item_name_1] => Dinner Plate [item_quantity_1] => 1 [item_price_1] => 5 [item_options_1] => code: 110 [item_name_2] => Side Plate [item_quantity_2] => 1 [item_price_2] => 4 [item_options_2] => code: 125 [item_name_3] => Mixing Bowl [item_quantity_3] => 1 [item_price_3] => 4 [item_options_3] => code: 66 )
What I am struggling with (and going around in circles) is a method to do the following..
Explode the [item_options] variable to strip out the CODE: part of the value and just leave the numeric section.
concatenate these values into a string so i can use a SELECT statement to only pull records that have an ID passed in the [item.options].
I understand how to explode a single parameter, but cannot work out how to loop through the array, explode the key and create the value i need for the SQL.
Any help or pointers to relevant tutorials would be much appreciated
$codes = array();
foreach ($_POST as $key => $value) { // Loop through the $_POST array
if (preg_match('/^item_options_/', $key)) { // And validate the value
$item_arr = explode(' ', $value);
$item_id = $item_arr[1]; // Get the ID number from the value
if (is_numeric($item_id)) { // Validate it
$codes[] = $item_id; // Add it to the array we're building
}
}
}
$codes_string = implode(', ', $codes); // Concatenate them into a string that can be used in a SQL IN clause
$sql = "SELECT * from table WHERE id IN ($codes_string)"; // Build the SQL

Resources