Codeigniter -> function using empty_table - php

I am trying to empty the tables but I was wondering have I got the function correct?
Model:
public function removeQuote()
{
$this->db->empty_table('companyDetails,hostingDetails,layoutDetails');
}
Controller:
public function submit()
{
$data['companyContact'] = $this->quote->getCompanyDetails()->companyContact;
$this->load->view('submit',$data);
$this->quote->removeQuote();
}
Error:
Table '_quote.companyDetails,hostingDetails,layoutDetails' doesn't exist
DELETE FROM `companyDetails,hostingDetails,layoutDetails`

/**
* Empty Table
*
* Compiles a delete string and runs "DELETE FROM table"
*
* #param string the table to empty
* #return object
*/
public function empty_table($table = '')
Apparently you can't do this
$this->db->empty_table('companyDetails,hostingDetails,layoutDetails');
Instead you will have to call empty_table three times:
$this->db->empty_table('companyDetails');
$this->db->empty_table('hostingDetails');
$this->db->empty_table('layoutDetails');
You can always hack CodeIgniter DB_active_rec.php file so that it fits your needs.

In your controller you have to load the model first (if it's not auto loaded)
$this->load->model('quote'); // Assuming your model name is 'quote'
before you use the function from that model as you used in your controller as follows
$data['companyContact'] = $this->quote->getCompanyDetails()->companyContact;
and load the view at last, after all code has been executed even after following line
$this->quote->removeQuote();
Just checked in CI doc empty_table doesn't accept multiple table names.

SOLUTION ONE
$this->db->truncate('companyDetails');
$this->db->truncate('hostingDetails');
$this->db->truncate('layoutDetails');
SOLUTION TWO
function emptytablesbycomma($stringoftables) {
$array_tablenames = explode(",", $stringoftables);
if (!empty($array_tablenames)) {
foreach ($array_tablenames as $tablename) {
$this->db->truncate($tablename);
}
}
}
Usage
$stringoftables='companyDetails,hostingDetails,layoutDetails';
$this->emptytablesbycomma($stringoftables);

Related

Laravel 8: How can I make an implicitly model bound route parameter optional instead of throwing 404?

I've tried to combine the Laravel docs on implicit binding and optional parameters and have the following code.
routes file:
Route::get('go/{example?}', [ExampleController::class, 'click'])->name('example');
And in the controller:
public function click(Example $example = null)
{
// Execution never reaches here
}
Execution never reaches the controller unless there is an Example with the correct slug, as it throws a 404. I want to check if $example is null in the controller and use custom logic there. How can this be accomplished?
Try this
Route::get('go/{example?}', [ExampleController::class, 'click'])->name('example');
public function click($example)
{
if($example != null){
$example = Example::findOrfail($example);
}
}
in model binding it will automatically run findOrfail to that model so don't you that so you will have control over it then you can manage
the #ettdro answer is perfect (and all credit is to him), but i think an answer with actual code would be useful:
routes:
Route::get('go/{example?}', [ExampleController::class, 'click'])->name('example');
controller:
public function click(Example $example)
{
// Stuff
}
Model of Example:
/**
* Retrieve the model for a bound value.
*
* #param mixed $value
* #param string|null $field
* #return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveRouteBinding($value, $field = null)
{
$result=$this->where('id', $value)->first();
return ($result)?$result:new Example();
}
You should obtain in the controller always a valid object, empty or not.
Had the same problem, and i'm happy with this solution.
To do that, you need use 'id' as your primary key in database and model,
if you are using another name for your pimary key, then you need to define it at your route:
Route::get('go/{example:number?}', [...]);

Laravel Controller Type Hinting

After creating a model with -mcr (php artisan make:model Institution -mrc), the show function in controller was scaffolded as:
/**
* Display the specified resource.
*
* #param \App\Organization\Institution $institution
* #return \Illuminate\Http\Response
*/
public function show(Institution $institution)
{
return view('institutions.show', ['institution' => $institution]);
}
The return view... was inserted by me. I was expecting it to have it populated with the object whose id was sent in the parameters.
/institutions/1
But, after using dd($institution), I verified that it has the ID, not the object.
Shouldn't this variable return me the object?
This is called Route Model Binding. Your route will need to look something like:
Route::get('institutions/{institution}', 'InstitutionController#show');
and then as per your controller
public function show(Institution $institution)
{
return view('institutions.show', compact($institution))
}
You can read more on this here.
I imagine your route had the parameter called {id} rather than {institution}.
Replace the parameter of show function
public function show(Institution $institution)
{
return view('institutions.show', compact($institution))
}
becomes
public function show($id)
{
$institution = App\Institution::findOrFail($id);;
return view('institutions.show', compact('institution'));
}
and in your routes
Route::get('institutions/{id}', 'InstitutionController#show');

`setAppends([])` on relation which is being loaded by `with` in Laravel

So for my project model setAppends([]) works as below:
Project::find($projectId)->setAppends([])
but what if I want to set appends to empty array for a relation which I'm eager loading with with, like below:
$project = Project::with('pages')->find($projectId);
->setAppends([]) not working in above code, as it will set it to empty array for Project not for Page.
Can anyone guide how to achieve that ?
Update:
page.php Model has appends and hidden like this:
class Page extends Model {
// I don't want to load this (`appends`) attributes when I call Project::find($projectId)
protected $appends = ['thumbnail_url', 'total_annotations', 'total_tasks', 'total_done_tasks', 'image_url', 'edited_data_items_count'];
protected $hidden = ['tasksCount', 'doneTasksCount', 'annotationsCount', 'xsl', 'xml', 'dataxml_version', 'sort_order', 'editedDataItemsCount', 'deletedDataItemsCount'];
}
Project.php model looks like this:
class Project extends Model {
use SoftDeletes;
protected $appends = ['total_tasks', 'total_done_tasks', 'total_pages', 'total_annotations', 'edited_dataitems_total_count'];
protected $hidden = ['tasksCount', 'doneTasksCount', 'pagesCount', 'annotationsCount', 'folder_path', 'attachment_url', 'pages'];
}
On Project you may provide a static method, which allows you to iterate over the eagerly loaded pages and adjust their append-array.
class Project
{
...
public static function eagerFindWithoutAppends($projectId)
{
$model = self::with('pages')->find($projectId);
$model->setAppends([]);
foreach ($model->pages as $page) {
$page->setAppends([]);
}
return $model;
}
...
}
But if I understand correctly, the dynamic data in your Pages class does more than just providing convenient shortcuts based on the regularly loaded data (such as something like getFullName which would combine first_name and last_name).
What do your appends do?
I don't want to load this (appends) attributes
Another possible solution I could think of is to inherit NoneAppendPages from Pages and override $append and all the related get... methods.
Then in Project declare another relationship to NoneAppendPages next to Pages. You then eager load Project::::with('none_append_pages')->find($projectId);
class NoneAppendPages extends Pages
{
protected $appends = [];
getYourDynamicAttributeMethodName() { return null; } // for all your appends
}
class Project
{
public function pages()
{
// I don't know what relationship you declared / assuming on to many
return $this->hasMany('App\Page');
}
public function noneAppendPages()
{
// declare the same way you did with pages
return $this->hasMany('App\NoneAppendPage');
}
}
The given solution does not work when using a package that does a lot of the work after you define the with() relations like datatables
here is a solution that works for any model.
<?php
namespace App\Database;
trait Appendable {
static protected $static_appends = [];
static protected $static_replace_appends = null;
/**
* set a static appends array to add to or replace the existing appends array..
* replace => totally replaces the existing models appends array at time of calling getArrayableAppends
* add => merges and then makes unique. when getArrayableAppends is called. also merges with the existing static_appends array
*
* #param $appendsArray
* #param bool $replaceExisting
*/
public static function setStaticAppends($appendsArray, $replaceExisting = true)
{
if($replaceExisting) {
static::$static_replace_appends = true;
static::$static_appends = array_unique($appendsArray);
} else {
static::$static_replace_appends = false;
static::$static_appends = array_unique(array_merge(static::$static_appends,$appendsArray));
}
}
/**
* Get all of the appendable values that are arrayable.
*
* #return array
*/
protected function getArrayableAppends()
{
if(!is_null(static::$static_replace_appends)) {
if(static::$static_replace_appends) {
$this->appends = array_unique(array_merge(static::$static_appends,$this->appends??[]));
} else {
$this->appends = static::$static_appends;
}
}
return parent::getArrayableAppends();
}
}
then you can just apply the trait to any model
<?php
namespace App\Database;
abstract class Company
{
use Appendable;
}
then call the static method BEFORE you use the relationship
<?php
$replaceCurrentAppendsArray = true;
// this will remove the original appends by replacing with empty array
\App\Database\Company::setStaticAppends([],$replaceCurrentAppendsArray);
$replaceCurrentAppendsArray = true;
// this will remove the original appends by replacing with smaller array
\App\Database\Company::setStaticAppends(['thumbnail_url'],$replaceCurrentAppendsArray);
$replaceCurrentAppendsArray = FALSE;
// this will add to the original appends by providing an additional array element
\App\Database\Company::setStaticAppends(['my_other_attribute'],$replaceCurrentAppendsArray);
this will allow you to override the appends array provided on the model even if another package is going to be loading the model. Like yajra/laravel-datatable where my issue was and brought me to this page which inspired a more dynamic solution.
This is similar to Stefan's second approach, but this is more dynamic so you do not have to create additional model extensions to accomplish the overrides.
You could take a similar approach to override the HidesAttribute trait as well.

Cannot access one particular model in Laravel, getting a BLANK page

I am trying to get distinct city names from a MySQL table called "city".
Here is how the controller code looks like:
public function getCityNames()
{
if(Auth::check())
{
$cities = DB::table('city')->distinct()->get();
var_dump($cities);
}
else
{
return Redirect::route('account-signin');
}
}
Here is the code for the model City:
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class City extends Eloquent
{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'city';
/**
* Using a different primary key name
*
*/
protected $primaryKey = 'geoname_id';
public $timestamps = false;
}
The Problem
I can output distinct values from other models using the exact code as in this controller above but when I run it for the city, I get a BLANK page.
I am using Laravel 4 with detailed error messages enabled.
Of course, there is data in the 'city' table
UPDATE:
When I write the following, I get data:
public function Test()
{
return City::where('country_name', '=', 'Canada')->get();
}
But when I write the following, I get the black page? Something with the data size?
public function Test()
{
return City::all()->get();
}
Not sure if this is problem, but are you trying to view the output of var_dump($cities)?
If so, shouldn't return var_dump($cities); give you the output, rather than the empty page?
Code looks like this:
public function getCityNames()
{
if(Auth::check()) // Tip: You can apply auth filters to controllers if you want.
{
$cities = DB::table('city')->distinct()->get();
return var_dump($cities); // Add return here.
}
else
{
return Redirect::route('account-signin');
}
// If the code doesn't go anywhere, it goes here.
return "TEST";
}
I am able to access the city table fine when I ran small queries (see my update in the question). Only explanation could be that I was exceeding the browser buffer size when I was trying to get all . This table has more than 70,000 rows.

Laravel Eloquent setting a default value for a model relation?

I have two models:
class Product extends Eloquent {
...
public function defaultPhoto()
{
return $this->belongsTo('Photo');
}
public function photos()
{
return $this->hasMany('Photo');
}
}
class Photo extends Eloquent {
...
public function getThumbAttribute() {
return 'products/' . $this->uri . '/thumb.jpg';
}
public function getFullAttribute() {
return 'products/' . $this->uri . '/full.jpg';
}
...
}
This works fine, I can call $product->defaultPhoto->thumb and $product->defaultPhoto->full and get the path to the related image, and get all photos using $product->photos and looping through the values.
The problem arises when the product does not have a photo, I can't seem to figure out a way to set a default value for such a scenario.
I have tried doing things such as
public function photos()
{
$photos = $this->hasMany('Photo');
if ($photos->count() === 0) {
$p = new Photo;
$p->url = 'default';
$photos->add($p);
}
return $photos;
}
I have also creating a completely new Collection to store the new Photo model in, but they both return the same error:
Call to undefined method Illuminate\Database\Eloquent\Collection::getResults()
Has anyone done anything similar to this?
Thanks in advance!
You could create an accessor on the Product model that did the check for you. Works the same if you just wanted to define it as a method, also (good for if you want to abstract some of the Eloquent calls, use an interface for your Product in case you change it later, etc.)
/**
* Create a custom thumbnail "column" accessor to retrieve this product's
* photo, or a default if it does not have one.
*
* #return string
*/
public function getThumbnailAttribute()
{
$default = $this->defaultPhoto;
return ( ! is_null($default))
? $default->thumb
: '/products/default/thumb.jpg';
}
You might also want to look into Presenters. A bit overkill for some situations, but incredibly handy to have (and abstract things like this away from your models).

Categories