In laravel 8 app when in pagination request I use mapping with calculated new field :
$hostelDataRows = Hostel
::orderBy('created_at', 'desc')
->where('hostels.id', 41) // debug
->with('state')
->with('region')
->with('user')
->withCount('hostelRooms')
->withCount('hostelInquiries')
->withCount('hostelImages')
->getByName($this->filters['name'], true)
->getByStatus($this->filters['status'], true)
->getByStateId($this->filters['state_id'], true)
->getByFeature($this->filters['feature'], true)
->addSelect([
'min_hostel_rooms_price' =>
HostelRoom::query()
->selectRaw('MIN(price)')
->whereColumn('hostel_id', 'hostels.id'),
])
->paginate($backend_per_page)
->map(function ($hostelItem) {
if ($hostelItem->hostel_rooms_count > 0 and $hostelItem->hostel_inquiries_count > 0 and $hostelItem->hostel_images_count > 0 ) {
$hostelItem->info_text = 'Has ' . ($hostelItem->hostel_rooms_count . pluralize3( $hostelItem->hostel_rooms_count, 'no rooms', 'room', 'rooms' ) );
}
return $hostelItem;
})
;
I got error :
Method Illuminate\Database\Eloquent\Collection::links does not exist. (
it is clear that with mappimg $hostelDataRows is not pagination object anyway...
How that can be fixed ?
Thanks!
When you use map() on a Paginator instance, you will get a Collection instance back (I think it is Illuminate\Database\Eloquent\Collection here). So you can't put map() in front of it since that would require you to fetch the query (which is dependent on the paginator page). However there are some other solutions:
Solution 1: use the tap() helper
The tap() helper always returns the argument to the function. Since Collection map() (and transform() which is very similar) modify the instance Collection itself, this works as intended and you now get your original paginator instance back (with the extra properties from your map-function).
return tap($query->paginate())->map(...);
Solution 2: use a getInfoTextAttribute() accessor
In your specific usecase you might just as well make a property for your $hostelItem if you are going to use this property more often, like so:
// Models/HostelItem.php
/**
* #property string $info_text
*/
class HostelItem extends Model
{
public function getInfoTextAttribute()
{
return 'Has ' . ($this->hostel_rooms_count . pluralize3( $this->hostel_rooms_count, 'no rooms', 'room', 'rooms' ) );
}
}
I've added a #property annotation so you can have code assist in most of your files. Now, simply call $hostelItem->info_text and you're done. no need for a map.
Related
I have six models that I need to get in one instance in my controller. How can I do that?
I have my six models:
CommentaireCritique
CommentaireNews
CommentaireDossier
CommentaireEpisode
CommentaireSerie
CommentaireTrailer
They all have the same structure in my database, and I would like to show the latest comms on one single page. I don't know if it's possible to bind them in a single controller. I tried that, but it's not working.
public function index()
{
$comms = CommentaireCritique::all() && CommentaireNews::all()
&& CommentaireDossier::all() && CommentaireEpisode::all()
&& CommentaireSerie::all() && CommentaireTrailer::all()
->get();
return view('admin.commentaires.index', compact('comms'));
}
just after the namespace , before the class declaration
use yourAppNameSpace/modelName
There is no limits to the number of models you can instantiate in your controller as long as you declare them above correctly.I think what you need is way to merge the result of all the models if that is so, then you have to use the merge method, otherwise can you please clarify a little bit your question.
yes, you can retrieve them at one controller,
you're already halfway there, you should separate on different variable
public function index()
{
$comms = CommentaireCritique::all()
$news = CommentaireNews::all()
$dossier = CommentaireDossier::all()
$episodes = CommentaireEpisode::all()
$series = CommentaireSerie::all()
$trailers = CommentaireTrailer::all()
return view('admin.commentaires.index', compact('comms','news','dossier','episodes','series','trailers'));
}
if you want put them in one variable, you can use collection docs
All of the results from all() function returns laravel collections. So use concat() function to concatenate all those into one collection
public function index()
{
$coms = CommentaireCritique::all()
->concat(CommentaireNews::all())
->concat(CommentaireDossier::all())
->concat(CommentaireEpisode::all())
->concat(CommentaireSerie::all())
->concat(CommentaireTrailer::all());
return view('admin.commentaires.index', compact('comms'));
}
I'm trying to generate something like 6B6E23518 using randomString() which I'm calling inside my controller
function randomString($chars=10) //generate random string
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randstring = '';
for ($i = 0; $i < $chars; $i++) {
$randstring .= $characters[rand(0, strlen($characters))];
}
return $randstring;
}
public function store(TicketsCreateRequest $request)
{
$ticket = $user->tickets()->create([
'ticket_hash' => $this->randomString(10),
// ....
]);
}
but this keeps on storing 0 into 'ticket_hash' and nothing gets generated??
Looking at your source code, is randomString() a public method of your controller class or is it a global function declared elsewhere outside of the class? I ask because it's entered above without the public visibility qualifier and with slightly different indentation to the method below it.
If this function is not an instanace method of your class, then your call to $this->randomString() is probably not calling the method you're expecting it to call. If your randomString() function is a global function defined elsewhere you should call it directly (eg. 'ticket_hash' => randomString(10),)
For what it's worth, for random strings like this it might be best to use the Laravel framework's Str class, only because it may be more stable and is definitely more widely used.
The Str::random() method achieves the output you're looking for in this case.
column ticket_hash was an integer type ,changed it to varchar and it works now.
I'm trying to understand how to use the laravel 5.0 command bus, but I am struggling to get it right, so I'm looking for help with a few questions:
I'd like to dispatch an array of memberIds to run through a loop inside the handle function of the command.
$members:
array:2 [
0 => "147"
1 => "148"
]
This array is sent like this:
$this->dispatch(new SendMail($members));
How do I access the array in the handle method of SendMail command? I haven't found many examples, but nearly all of them pass $command into the handler.
public function handle($command)
{
//this doesn't work
foreach($command->members as $memberId){
$contractor = Contractor::find($memberId);
}
Do I need to return anything from the handler in order to continue running the other logic inside of my original function?
Since your trying to inject your $members array to your job's constructor method, you need to handle it there.
Then you'll be able to use your array in the hanle method.
// in your job class
protected $members;
public function __construct($members)
{
$this->members = $members
}
public function handle ()
{
foreach ($this->members as $member) {
//your logic
}
}
And if you want to inject an Eloquent model to your job (instead of an array) remember that you can typehint directtly in the constructor and , using the SerializesModels trait Laravel will retrieve it for you. This is described in the documentation.
I'm working with the latest codeIgniter released, and i'm also working with jquery datatables from datatables.net
I've written this function: https://gist.github.com/4478424 which, as is works fine. Except when I filter by using the text box typing something in. The filter itself happens, but my count is completely off.
I tried to add in $res = $this->db->count_all_results() before my get, and it stops the get from working at all. What I need to accomplish, if ($data['sSearch'] != '') then to utilize the entire query without the limit to see how many total rows with the search filter exists.
If you need to see any other code other than whats in my gist, just ask and I will go ahead and post it.
$this->db->count_all_results() replaces $this->db->get() in a database call.
I.E. you can call either count_all_results() or get(), but not both.
You need to do two seperate active record calls. One to assign the results #, and one to get the actual results.
Something like this for the count:
$this->db->select('id');
$this->db->from('table');
$this->db->where($your_conditions);
$num_results = $this->db->count_all_results();
And for the actual query (which you should already have):
$this->db->select($your_columns);
$this->db->from('table');
$this->db->where($your_conditions);
$this->db->limit($limit);
$query = $this->db->get();
Have you read up on https://www.codeigniter.com/userguide2/database/active_record.html#caching ?
I see you are trying to do some pagination where you need the "real" total results and at the same time limiting.
This is my practice in most of my codes I do in CI.
$this->db->start_cache();
// All your conditions without limit
$this->db->from();
$this->db->where(); // and etc...
$this->db->stop_cache();
$total_rows = $this->db->count_all_results(); // This will get the real total rows
// Limit the rows now so to return per page result
$this->db->limit($per_page, $offset);
$result = $this->db->get();
return array(
'total_rows' => $total_rows,
'result' => $result,
); // Return this back to the controller.
I typed the codes above without testing but it should work something like this. I do this in all of my projects.
You dont actually have to have the from either, you can include the table name in the count_all_results like so.
$this->db->count_all_results('table_name');
Count first with no_reset_flag.
$this->db->count_all_results('', FALSE);
$rows = $this->db->get()->result_array();
system/database/DB_query_builder.php
public function count_all_results($table = '', $reset = TRUE) { ... }
The
$this->db->count_all_results();
actually replaces the:
$this->db->get();
So you can't actually have both.
If you want to do have both get and to calculate the num rows at the same query you can easily do this:
$this->db->from(....);
$this->db->where(....);
$db_results = $this->get();
$results = $db_results->result();
$num_rows = $db_results->num_rows();
Try this
/**
* #param $column_name : Use In Choosing Column name
* #param $where : Use In Condition Statement
* #param $table_name : Name of Database Table
* Description : Count all results
*/
function count_all_results($column_name = array(),$where=array(), $table_name = array())
{
$this->db->select($column_name);
// If Where is not NULL
if(!empty($where) && count($where) > 0 )
{
$this->db->where($where);
}
// Return Count Column
return $this->db->count_all_results($table_name[0]);//table_name array sub 0
}
Then Simple Call the Method
Like this
$this->my_model->count_all_results(['column_name'],['where'],['table name']);
If your queries contain a group by, using count_all_results fails. I wrote a simple method to work around this. The key to preventing writing your queries twice is to put them all inside a private method that can be called twice. Here is some sample code:
class Report extends CI_Model {
...
public function get($page=0){
$this->_complex_query();
$this->db->limit($this->results_per_page, $page*$this->results_per_page);
$sales = $this->db->get()->result(); //no table needed in get()
$this->_complex_query();
$num_results = $this->_count_results();
$num_pages = ceil($num_results/$this->results_per_page);
//return data to your controller
}
private function _complex_query(){
$this->db->where('a', $value);
$this->db->join('(subquery) as s', 's.id = table.s_id');
$this->db->group_by('table.column_a');
$this->db->from('table'); //crucial - we specify all tables here
}
private function _count_results(){
$query = $this->db->get_compiled_select();
$count_query = "SELECT count(*) as num_rows FROM (".$query.") count_wrap";
$r = $this->db->query($count_query)->row();
return $r->num_rows;
}
}
Here is my function. It is very simple.
function load_data() {
$query = $this->db->query('SELECT * FROM configurations WHERE username="' . $this->session->userdata('username') . '"');
return $query;
}
My controller has this line of code:
$data['query'] = $this->configurations->load_data();
In my view, I tried:
foreach($query->result_array() as $row) {
echo $row->first;
}
But I get an error that I am trying to get a property of a non-object. Isn't the query being returned from the model as an object?
You should use $query->result_array, row_array, result, or row otherwise your returning the object intead get the results. Check the CI manual.
You are returning the results as array and using $row as object!
Try:
foreach($query->result() as $row) {
Refer.
Try changing $this->load->model('login/configurations', '', TRUE); to $this->load->model('login/configurations', 'configurations', TRUE); and see if it works. If it does, it is related to how you're extending your model class. That is, it would be related to what name you give inside configurations.php.
Hope this helps.
Your undefined variable error tells me that your query might not be running correctly. To diagnose...enable the profiler to check your query.
From the documentation:
$this->output->enable_profiler();
Permits you to enable/disable the
Profiler, which will display benchmark
and other data at the bottom of your
pages for debugging and optimization
purposes.
To enable the profiler place the
following function anywhere within
your Controller functions:
$this->output->enable_profiler(TRUE);
When enabled a report will be
generated and inserted at the bottom
of your pages.
Your query will be shown at the end of
the page
Double check your query syntax to make sure it is running properly, and
your code in it's current state is returning an object of objects and arrays:
print_r($query)
CI_DB_mysql_result Object
(
[conn_id] => Resource id #29
[result_id] => Resource id #39
[result_array] => Array
(
)
[result_object] => Array
(
)
[current_row] => 0
[num_rows] => 3
[row_data] =>
)
you need to access the individual properties to get to the actual data.
$result=$query->result();
print_r($result);
should do it
Had this issue before - basic problem is that if the Query returns no result set then $query->result_array() == NULL
NULL is not a list and can't be processed in a foreach.
I have found that checking for this condition solves this issue.
From your question, you are getting the result as a pure array (result_array) but printing the data as object ($row->first).
result() or row() is returning in object but result_array is returning in array.
change your view part like,
foreach($query->result_array() as $row) {
echo $row['first'];
}
or if you want to use an object then,
foreach($query->result() as $row) {
echo $row->first;
}
Generating Query Results in Codeigniter