I have been trying to find the best way to create a cache wrapper for all models. So all the DB lookup are done through the model, but the model decides if the results should be stored in cache.
For example, when I search for a user by email, I want to do something like User->getByEmail('test#exmaple.com');
My User model would contain a function that looks something like
public static function getByEmail($email) {
$cache = self::cacheFetch($email);
if($cache) {
return $cache;
}
// DB lookup to get data
self::cacheStore($email, $data);
return $data;
}
cacheFetch and cacheStore are defined as traits. The App name and table name are prepended to the cache key to avoid key clash.
How do I do the database lookup within the Model?
Is there a better way to achieve what I am trying to do here?
You actually only need one function, cacheFetch. This function would check if the queried data is in cache and if not, load the data from the database.
This is a small example of how the function could work:
protected function cacheFetch($email)
{
$slug = 'db_' . self::getTable() . '_' . $email;
// Try fetching data from cache
if (cache()->has($slug)) {
return cache($slug);
}
// Fetch data from database and put in cache
$data = self::where('email', $email)->get();
cache()->put($slug, $data, 60);
return $data;
}
Related
Is possible to attach a custom attribute when retrieving a model in laravel?.
The problem is that I need to return some data that is not in the database along the info from the database. I've been doing it manually but I guess that there might be a way to do it in the model.
Example: I have an application table. Each application contains a folder with documents with the same application id. I need to attach the amount of files the folder that correspond to each application.
This is what I do:
$application = Application::get();
$application = $application->map(function($a){
$a->files = $this->getFiles($a->id); // This gets the amount of files
return $a;
})
Is there some way to do it in the model in a way that $application->files is already contained in $application when doing Application::get()
class User extends Model
{
public function getFooBarAttribute()
{
return "foobar";
}
}
And access to that attribute like:
$user->foo_bar;
or like,
$user->fooBar;
More detailed documentation;
https://laravel.com/docs/5.7/eloquent-mutators#defining-an-accessor
in the Application model
public function getFilesAttribute()
{
return 'lala'; // return whatever you need;
}
now application model has an attribute named files.
$application->files // returns lala.
example code.
$applications = Application::get();
$application_files = applications->map->files;
official documentation https://laravel.com/docs/5.7/eloquent-mutators#defining-an-accessor
I am working with the save event but having limited luck.
I have currently tried two ways but to limited success.
1) I can either never get the function to fire,
2) I am not too sure what to pass into the function for method two.
All I am trying to do is to dump the event information out on content save.Any help greatly appreciated, really loving this CMS
Attempt One -- never runs the function at all
class Extension extends BaseExtension
{
public function initialize() {
$this->addCss('assets/extension.css');
$this->addJavascript('assets/start.js', true);
$this->app['dispatcher']->addListener(\Bolt\Events\StorageEvents::POST_SAVE, 'postSave');
}
function postSave(\Bolt\StorageEvent $event)
{
dump($event);
}
Attempt two -- what do I input as a parameter?
class Extension extends BaseExtension
{
public function initialize() {
$this->addCss('assets/extension.css');
$this->addJavascript('assets/start.js', true);
$this->app['dispatcher']->addListener(\Bolt\Events\StorageEvents::POST_SAVE,$this->postsave($this->?????));
}
function postSave(\Bolt\StorageEvent $event)
{
dump($event);
}
Hopefully my answer doesn't come too late!
You simply can modify the content and save it back to the database:
public function postSave(\Bolt\Events\StorageEvent $event) {
// get the content
$content = $event->getContent();
// get a field out of the contenttype
$data = $content->get("myField");
// now modify $data here
$data = "new data - what ever you want";
// set data to the content
$content->setValue("data", $data);
// write the modified content to the database
$this->app['storage']->saveContent($content);
}
Note that the function gets fired every time you save contents. So just add an if-statement like this to just modify content you really want to:
if ($event->getContentType() == "my_type")
The parameter needed is a php callback the format for this is something like this:
$this->app['dispatcher']->addListener(\Bolt\Events\StorageEvents::POST_SAVE, array($this, 'postSave'));
That syntax is saying to run the postSave method within the current class. So this would work with your example number 1.
Now you can dump the event in your postSave method and see the results.
I'm trying to pass an array from a function to another function in laravel.
In my PageController.php, I have
public function show($code, $id){
//some code
if(isset($search))
dd($search);
}
and another function
public function search($code, $id){
//some queries
$result = DB::table('abd')->get();
return Redirect::action('PageController#show, ['search'=>$search]);
}
But this returns me an error like this: ErrorException (E_UNKNOWN)
Array to string conversion
I'm using laravel.
You could maybe get it to work with passing by the URL by serialization, but I'd rather store it in a session variable. The session class has this nice method called flash which will keep the variable for the next request and then automatically remove it.
Also, and that's just a guess, you probably need to use the index action for that, since show needs the id of a specific resource.
public function search($code, $id){
//some queries
$result = DB::table('abd')->get();
Session::flash('search', $search); // or rather $result?
return Redirect::action('PageController#index');
}
public function index($code){
//some code
if(Session::has('search')){
$search = Session::get('search');
dd($search);
}
}
I have an array that loaded data from excel, now I need to send this data to another view for a review of test, but this not found because is a array in a function, I try to use serialize and unserialize but this send a error of limit of characteres in the url.
public function excel() {
$this->loadModel('SoyaProductorCompra');
$excel=array();
$k=0;
if ($this->request->is('post')) {
$datos = new Spreadsheet_Excel_Reader();
$datos->read($this->request->data['SoyaProductorCompra']['excel']['tmp_name']);
for ($i = 2; $i <= $datos->sheets[0]['numRows']; $i++) {
$excel[$k]['producto']=$datos->sheets[0]['cells'][$i][1];
$excel[$k]['toneladas']=$datos->sheets[0]['cells'][$i][2];
$excel[$k]['precio']=$datos->sheets[0]['cells'][$i][3];
$excel[$k]['total']=$datos->sheets[0]['cells'][$i][4];
$excel[$k]['fecha']=$datos->sheets[0]['cells'][$i][5];
$excel[$k]['id']=$datos->sheets[0]['cells'][$i][6];
$k++;
}
$this->set('excels',$excel);
//return $this->redirect(array('action' => 'revision', serialize($excel))); not found
}
}
this is my other function that recive the array and show in my view but not found
public function revicionexcel($data) {
//$data=unserialize($data); not work
//debug($data); not work
}
I wouldn't send the data of a whole spreadsheet through a query string regardless, even if it were small enough to do that. I mean, what would happen if someone started manually editing the URL for instance? Either write the data to a file, or save it in the session instead.
It seems that you're calling the funciton inside the same controller, right?
If so, then why you just don't use:
public function excel()
{
//read excel into $excel variable
$this->revicionexcel($excel);
}
so, no need of redirects here
Although it's recommended that you have the excel reading in the model layer, as this layer is intended for all kind of data management.
Edit:
Then, based on your comments, you can move all the reading to the model, and call it from the controller:
SoyaProductorCompra model:
public function excel($data) {
//your excel reading function as you have it on the controller.
//change all "$this->request->data" references for the parameter "$data"
//be sure to return the excel properly.
...
return $excel;
}
SoyaProductorCompras controller:
public function revision()
{
$excel = $this->SoyaProductorCompra->excel($this->request->data);
$this->set('excels', $excel);
}
What we're doing here is to call the excel opening in the model from the action revision(), and sending them to its view. You don't need to redirect here.
How can i do the followin tasks
public function addToCache($id,$items)
{
// in zend cache
}
public function getFromCache($id)
{
// in zend cache
}
The first method should take an id and items which should be cached.
The second method should just take an id of an cached object, and should return the content of the cache of that item id.
i want to be able to do something like that;
public function getItems()
{
if(!$this->cache->getFromCache('items'))
{
$this->addToCache('items',$this->feeds->items());
return $this->cache->getFromCache('items');
}
}
How can i do the both methods in zend cache ?
Everything to get started is in the Zend docs. You do have to dig in a little and get comfortable, it's not a "quick how do I do this" type of area.
But, the general cache-check looks like this:
$cache = /*cache object*/
if ( !($my_object = unserialize($cache->load('cache_key'))) ) {
$my_object = /*not found so initialize your object*/
$cache->save(serialize($my_object)); // magically remembers the above 'cache_key'
}
$my_object->carryOnAsIfNothingStrangeJustHappenedThere();
Assuming that you have already set up an instance of Zend_Cache and have access to it through a local variable $this->cache, your functions would be implemented as:
function getFromCache($key) { return $this->cache->load($key); }
function addToCache($key,$value) { $this->cache->save($key,$value); }